--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / frontend / components / messages / ConversationViewer.vue
Displaying Raw • Download
meshchatx/src/frontend/components/messages/ConversationViewer.vue ea8ef555c260fe3d201c254b37561818c985ed5d (ea8ef555) Text, 109.73 KB
Tb4b4b4<Tff7b72templateTb4b4b4>
T8b949e<!-- peer selected -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"flex flex-col h-full bg-white dark:bg-zinc-950 overflow-hidden transition-all"Tb4b4b4>
T8b949e<!-- header -->
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"flex items-center px-4 py-3 border-b border-gray-200/60 dark:border-zinc-800/60 bg-white/80 dark:bg-zinc-900/50 backdrop-blur-sm"
Tb4b4b4>
T8b949e<!-- peer icon -->
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"flex-shrink-0 mr-3"Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerTb4b4b4.Te6edf3lxmf_user_iconTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"p-2 rounded shadow-sm"
Tb4b4b4:Te6edf3styleTff7b72=Ta5d6ff"Tb4b4b4{
Te6edf3colorTff7b72: Te6edf3selectedPeerTb4b4b4.Te6edf3lxmf_user_iconTb4b4b4.Te6edf3foreground_colourTb4b4b4,
Ta5d6ff'background-color'Tff7b72: Te6edf3selectedPeerTb4b4b4.Te6edf3lxmf_user_iconTb4b4b4.Te6edf3background_colourTb4b4b4,
Tb4b4b4}Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Tb4b4b4:Te6edf3icon-nameTff7b72=Ta5d6ff"Te6edf3selectedPeerTb4b4b4.Te6edf3lxmf_user_iconTb4b4b4.Te6edf3icon_nameTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"w-6 h-6" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3v-else Te6edf3classTff7b72=Ta5d6ff"bg-gray-200 dark:bg-zinc-700 text-gray-500 dark:text-gray-400 p-2 rounded shadow-sm"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"account-outline" Te6edf3classTff7b72=Ta5d6ff"w-6 h-6" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- peer info -->
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"min-w-0 flex-1"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"flex items-center cursor-pointer min-w-0 group" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3updateCustomDisplayNameTa5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerTb4b4b4.Te6edf3custom_display_name Tff7b72!= Tff7b72nullTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"mr-1.5 text-gray-500 dark:text-zinc-400 group-hover:text-gray-700 dark:group-hover:text-zinc-200 transition-colors"
Tb4b4b4:Te6edf3titleTff7b72=Ta5d6ff"Te6edf3$tTb4b4b4(Ta5d6ff'messages.custom_display_name'Tb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-3.5 h-3.5"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"M9.568 3H5.25A2.25 2.25 0 0 0 3 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 0 0 5.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 0 0 9.568 3Z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72path Te6edf3stroke-linecapTff7b72=Ta5d6ff"round" Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round" Te6edf3dTff7b72=Ta5d6ff"M6 6h.008v.008H6V6Z" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"font-semibold text-gray-900 dark:text-zinc-100 truncate max-w-xs sm:max-w-sm text-base"
Tb4b4b4:Te6edf3titleTff7b72=Ta5d6ff"Te6edf3selectedPeerTb4b4b4.Te6edf3custom_display_name Tff7b72?? Te6edf3selectedPeerTb4b4b4.Te6edf3display_nameTa5d6ff"
Tb4b4b4>
Tff7b72{{ Te6edf3selectedPeerTb4b4b4.Te6edf3custom_display_name Tff7b72?? Te6edf3selectedPeerTb4b4b4.Te6edf3display_name Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"text-xs text-gray-500 dark:text-zinc-400 mt-0.5"Tb4b4b4>
T8b949e<!-- destination hash -->
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"inline-block mr-1"Tb4b4b4>
Tb4b4b4<Tff7b72divTb4b4b4>Te6edf3<Tff7b72{{ Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hash Tff7b72}}Te6edf3>Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"inline-block"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"flex space-x-1"Tb4b4b4>
T8b949e<!-- hops away -->
Tb4b4b4<Tff7b72span
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerPathTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"flex my-auto cursor-pointer"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3onDestinationPathClickTb4b4b4(Te6edf3selectedPeerPathTb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerPathTb4b4b4.Te6edf3hops Tff7b72=== T79c0ff0 Tff7b72|| Te6edf3selectedPeerPathTb4b4b4.Te6edf3hops Tff7b72=== T79c0ff1Ta5d6ff"Tb4b4b4>Tff7b72{{
Te6edf3$tTb4b4b4(Ta5d6ff"messages.direct"Tb4b4b4)
Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3v-elseTb4b4b4>Tff7b72{{ Te6edf3$tTb4b4b4(Ta5d6ff"messages.hops_away"Tb4b4b4, Tb4b4b4{ Te6edf3countTff7b72: Te6edf3selectedPeerPathTb4b4b4.Te6edf3hops Tb4b4b4}Tb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
T8b949e<!-- snr -->
Tb4b4b4<Tff7b72span Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerSignalMetricsTff7b72?Tb4b4b4.Te6edf3snr Tff7b72!= Tff7b72nullTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"flex my-auto space-x-1"Tb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerPathTa5d6ff"Tb4b4b4>•Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3classTff7b72=Ta5d6ff"cursor-pointer" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3onSignalMetricsClickTb4b4b4(Te6edf3selectedPeerSignalMetricsTb4b4b4)Ta5d6ff"Tb4b4b4>Tff7b72{{
Te6edf3$tTb4b4b4(Ta5d6ff"messages.snr"Tb4b4b4, Tb4b4b4{ Te6edf3snrTff7b72: Te6edf3selectedPeerSignalMetricsTb4b4b4.Te6edf3snr Tb4b4b4}Tb4b4b4)
Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
T8b949e<!-- stamp cost -->
Tb4b4b4<Tff7b72span Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerLxmfStampInfoTff7b72?Tb4b4b4.Te6edf3stamp_costTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"flex my-auto space-x-1"Tb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerPath Tff7b72|| Te6edf3selectedPeerSignalMetricsTff7b72?Tb4b4b4.Te6edf3snr Tff7b72!= Tff7b72nullTa5d6ff"Tb4b4b4>•Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3classTff7b72=Ta5d6ff"cursor-pointer" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3onStampInfoClickTb4b4b4(Te6edf3selectedPeerLxmfStampInfoTb4b4b4)Ta5d6ff"Tb4b4b4>Tff7b72{{
Te6edf3$tTb4b4b4(Ta5d6ff"messages.stamp_cost"Tb4b4b4, Tb4b4b4{ Te6edf3costTff7b72: Te6edf3selectedPeerLxmfStampInfoTb4b4b4.Te6edf3stamp_cost Tb4b4b4}Tb4b4b4)
Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- dropdown menu -->
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"ml-auto flex items-center gap-1"Tb4b4b4>
Tb4b4b4<Tff7b72ConversationDropDownMenu
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerTa5d6ff"
Tb4b4b4:Te6edf3peerTff7b72=Ta5d6ff"Te6edf3selectedPeerTa5d6ff"
Tb4b4b4@Te6edf3conversation-deletedTff7b72=Ta5d6ff"Te6edf3onConversationDeletedTa5d6ff"
Tb4b4b4@Te6edf3set-custom-display-nameTff7b72=Ta5d6ff"Te6edf3updateCustomDisplayNameTa5d6ff"
Tb4b4b4@Te6edf3block-status-changedTff7b72=Ta5d6ff"Te6edf3loadBlockedDestinationsTa5d6ff"
Tb4b4b4/Tb4b4b4>
T8b949e<!-- popout button -->
Tb4b4b4<Tff7b72IconButton Tb4b4b4:Te6edf3titleTff7b72=Ta5d6ff"Te6edf3$tTb4b4b4(Ta5d6ff'messages.pop_out_chat'Tb4b4b4)Ta5d6ff" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3openConversationPopoutTa5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"open-in-new" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72IconButtonTb4b4b4>
T8b949e<!-- share contact button -->
Tb4b4b4<Tff7b72IconButton Te6edf3titleTff7b72=Ta5d6ff"Share Contact" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3openShareContactModalTa5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"notebook-outline" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72IconButtonTb4b4b4>
T8b949e<!-- close button -->
Tb4b4b4<Tff7b72IconButton Te6edf3titleTff7b72=Ta5d6ff"Close" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3closeTa5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72svg Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg" Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 20 20" Te6edf3fillTff7b72=Ta5d6ff"currentColor" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4"Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3dTff7b72=Ta5d6ff"M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72IconButtonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- Share Contact Modal -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3isShareContactModalOpenTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm"
Tb4b4b4@Te6edf3clickTb4b4b4.Te6edf3selfTff7b72=Ta5d6ff"Te6edf3isShareContactModalOpen Tff7b72= Tff7b72falseTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"w-full max-w-md bg-white dark:bg-zinc-900 rounded-2xl shadow-2xl overflow-hidden"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"px-6 py-4 border-b border-gray-100 dark:border-zinc-800 flex items-center justify-between"Tb4b4b4>
Tb4b4b4<Tff7b72h3 Te6edf3classTff7b72=Ta5d6ff"text-lg font-bold text-gray-900 dark:text-white"Tb4b4b4>Share ContactTb4b4b4<Tb4b4b4/Tff7b72h3Tb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"text-gray-400 hover:text-gray-500 dark:hover:text-zinc-300 transition-colors"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3isShareContactModalOpen Tff7b72= Tff7b72falseTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"close" Te6edf3classTff7b72=Ta5d6ff"size-6" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"p-6"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"mb-4"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"relative"Tb4b4b4>
Tb4b4b4<Tff7b72input
Te6edf3v-modelTff7b72=Ta5d6ff"Te6edf3contactsSearchTa5d6ff"
Te6edf3typeTff7b72=Ta5d6ff"text"
Te6edf3placeholderTff7b72=Ta5d6ff"Search contacts..."
Te6edf3classTff7b72=Ta5d6ff"block w-full rounded-lg border-0 py-2 pl-10 text-gray-900 dark:text-white shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-zinc-800 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm dark:bg-zinc-900"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"magnify" Te6edf3classTff7b72=Ta5d6ff"size-5 text-gray-400" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"max-h-64 overflow-y-auto space-y-2"Tb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3v-forTff7b72=Ta5d6ff"Te6edf3contact Tff7b72in Te6edf3filteredContactsTa5d6ff"
Tb4b4b4:Te6edf3keyTff7b72=Ta5d6ff"Te6edf3contactTb4b4b4.Te6edf3idTa5d6ff"
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"w-full flex items-center gap-3 p-3 rounded-xl hover:bg-gray-50 dark:hover:bg-zinc-800 transition-colors text-left"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3shareContactTb4b4b4(Te6edf3contactTb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"size-10 rounded-full bg-blue-50 dark:bg-blue-900/20 text-blue-500 flex items-center justify-center shrink-0"
Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"account" Te6edf3classTff7b72=Ta5d6ff"size-6" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"min-w-0"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"font-bold text-gray-900 dark:text-white truncate"Tb4b4b4>
Tff7b72{{ Te6edf3contactTb4b4b4.Te6edf3name Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"text-[10px] text-gray-500 dark:text-zinc-500 font-mono truncate"Tb4b4b4>
Tff7b72{{ Te6edf3contactTb4b4b4.Te6edf3remote_identity_hash Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- chat items -->
Tb4b4b4<Tff7b72div
Te6edf3idTff7b72=Ta5d6ff"messages"
Te6edf3classTff7b72=Ta5d6ff"h-full overflow-y-scroll bg-gray-50/30 dark:bg-zinc-950/50"
Tb4b4b4@Te6edf3scrollTff7b72=Ta5d6ff"Te6edf3onMessagesScrollTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3selectedPeerChatItemsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Ta5d6ff" Te6edf3classTff7b72=Ta5d6ff"flex flex-col flex-col-reverse px-4 py-6"Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3v-forTff7b72=Ta5d6ff"Te6edf3chatItem Tff7b72of Te6edf3selectedPeerChatItemsReversedTa5d6ff"
Tb4b4b4:Te6edf3keyTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"flex flex-col max-w-[75%] sm:max-w-[65%] lg:max-w-[55%] mb-4 group"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"Tb4b4b4{ Ta5d6ff'ml-auto items-end'Tff7b72: Te6edf3chatItemTb4b4b4.Te6edf3is_outboundTb4b4b4, Ta5d6ff'mr-auto items-start'Tff7b72: Tff7b72!Te6edf3chatItemTb4b4b4.Te6edf3is_outbound Tb4b4b4}Ta5d6ff"
Tb4b4b4>
T8b949e<!-- message content -->
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"relative rounded-2xl overflow-hidden transition-all duration-200 hover:shadow-md"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"Tb4b4b4[
Tb4b4b4[Ta5d6ff'cancelled'Tb4b4b4, Ta5d6ff'failed'Tb4b4b4]Tb4b4b4.Te6edf3includesTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3stateTb4b4b4)
Tff7b72? Ta5d6ff'bg-red-500 text-white shadow-sm'
Tff7b72: Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3is_spam
Tff7b72? Ta5d6ff'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-900 dark:text-yellow-100 border border-yellow-300 dark:border-yellow-700 shadow-sm'
Tff7b72: Te6edf3chatItemTb4b4b4.Te6edf3is_outbound
Tff7b72? Ta5d6ff'bg-blue-600 text-white shadow-sm'
Tff7b72: Ta5d6ff'bg-white dark:bg-zinc-900 text-gray-900 dark:text-zinc-100 border border-gray-200/60 dark:border-zinc-800/60 shadow-sm'Tb4b4b4,
Tb4b4b4]Ta5d6ff"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3onChatItemClickTb4b4b4(Te6edf3chatItemTb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"w-full space-y-1 px-4 py-2.5"Tb4b4b4>
T8b949e<!-- spam badge -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3is_spamTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"flex items-center gap-1.5 text-xs font-medium mb-1"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3is_outbound Tff7b72? Ta5d6ff'text-yellow-200' Tff7b72: Ta5d6ff'text-yellow-700 dark:text-yellow-300'
Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"2"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-4 h-4"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Marked as SpamTb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- content -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3contentTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"text-sm leading-relaxed whitespace-pre-wrap break-words"
Te6edf3styleTff7b72=Ta5d6ff"font-family: inherit"
Tb4b4b4>
Tff7b72{{ Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3content Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- image field -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3imageTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"relative group mt-1 -mx-1"Tb4b4b4>
Tb4b4b4<Tff7b72img
Tb4b4b4:Te6edf3srcTff7b72=Ta5d6ff"Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/attachment/Tffd700${Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTffd700}Ta5d6ff/imageTa5d6ff`Ta5d6ff"
Te6edf3classTff7b72=Ta5d6ff"w-full rounded-lg cursor-pointer transition-transform group-hover:scale-[1.01]"
Tb4b4b4@Te6edf3clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"
Te6edf3openImageTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/attachment/Tffd700${Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTffd700}Ta5d6ff/imageTa5d6ff`
Tb4b4b4)
Ta5d6ff"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"absolute bottom-2 left-2 bg-black/60 backdrop-blur-sm text-white text-xs px-2.5 py-1 rounded-lg flex items-center gap-1.5"
Tb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Tff7b72{{
Tb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3imageTb4b4b4.Te6edf3image_type Tff7b72?? Ta5d6ff"image"Tb4b4b4)Tb4b4b4.Te6edf3toUpperCaseTb4b4b4(Tb4b4b4)
Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>•Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Tff7b72{{ Te6edf3formatAttachmentSizeTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3imageTb4b4b4, Ta5d6ff"image"Tb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- audio field -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3audioTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"pb-1"Tb4b4b4>
T8b949e<!-- audio is loaded -->
Tb4b4b4<Tff7b72audio
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3lxmfMessageAudioAttachmentCacheTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4]Ta5d6ff"
Tb4b4b4:Te6edf3srcTff7b72=Ta5d6ff"Te6edf3lxmfMessageAudioAttachmentCacheTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4]Ta5d6ff"
Te6edf3controls
Te6edf3classTff7b72=Ta5d6ff"w-full rounded-lg shadow-sm"
Te6edf3styleTff7b72=Ta5d6ff"height: 54px"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3is_outbound Tff7b72? Ta5d6ff'audio-controls-light' Tff7b72: Ta5d6ff'audio-controls-dark'Ta5d6ff"
Tb4b4b4>Tb4b4b4<Tb4b4b4/Tff7b72audioTb4b4b4>
T8b949e<!-- audio is not yet loaded -->
T8b949e<!-- min height to make sure audio player doesn't cause height increase after loading -->
Tb4b4b4<Tff7b72div Te6edf3v-else Te6edf3styleTff7b72=Ta5d6ff"min-height: 54px" Te6edf3classTff7b72=Ta5d6ff"flex"Tb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"my-auto flex items-center gap-2 border border-gray-200/60 dark:border-zinc-700 hover:bg-gray-50 dark:hover:bg-zinc-800 rounded-lg px-3 py-2 text-sm font-medium transition-colors"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3is_outbound
Tff7b72? Ta5d6ff'bg-white/20 text-white border-white/20 hover:bg-white/30'
Tff7b72: Ta5d6ff'bg-gray-50 dark:bg-zinc-800/50 text-gray-700 dark:text-zinc-300'
Ta5d6ff"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3downloadAndDecodeAudioTb4b4b4(Te6edf3chatItemTb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"size-6"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"m9 9 10.5-3m0 6.553v3.75a2.25 2.25 0 0 1-1.632 2.163l-1.32.377a1.803 1.803 0 1 1-.99-3.467l2.31-.66a2.25 2.25 0 0 0 1.632-2.163Zm0 0V2.25L9 5.25v10.303m0 0v3.75a2.25 2.25 0 0 1-1.632 2.163l-1.32.377a1.803 1.803 0 0 1-.99-3.467l2.31-.66A2.25 2.25 0 0 0 9 15.553Z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3classTff7b72=Ta5d6ff"my-auto w-full"Tb4b4b4>
Tff7b72{{
Te6edf3isDownloadingAudioTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4]
Tff7b72? Ta5d6ff"Downloading..."
Tff7b72: Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4.Te6edf3audio_mode Tff7b72=== T79c0ff0x10
Tff7b72? Ta5d6ff"Load Audio"
Tff7b72: Ta5d6ff"Load Audio (Codec2)"
Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-6 h-6"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"
Te6edf3isDownloadingAudioTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4]
Tff7b72? Ta5d6ff'animate-bounce'
Tff7b72: Ta5d6ff''
Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"text-xs mt-1.5"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3is_outbound Tff7b72? Ta5d6ff'text-white/70' Tff7b72: Ta5d6ff'text-gray-500 dark:text-zinc-400'Ta5d6ff"
Tb4b4b4>
Audio • Tff7b72{{ Te6edf3formatAttachmentSizeTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4, Ta5d6ff"audio"Tb4b4b4) Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- file attachment fields -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3file_attachmentsTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"space-y-2 mt-1"Tb4b4b4>
Tb4b4b4<Tff7b72a
Te6edf3v-forTff7b72=Ta5d6ff"Tb4b4b4(Te6edf3file_attachmentTb4b4b4, Te6edf3indexTb4b4b4) Tff7b72of Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3file_attachments Tff7b72??
Tb4b4b4[Tb4b4b4]Ta5d6ff"
Tb4b4b4:Te6edf3keyTff7b72=Ta5d6ff"Te6edf3file_attachmentTb4b4b4.Te6edf3file_nameTa5d6ff"
Te6edf3targetTff7b72=Ta5d6ff"_blank"
Tb4b4b4:Te6edf3downloadTff7b72=Ta5d6ff"Te6edf3file_attachmentTb4b4b4.Te6edf3file_nameTa5d6ff"
Tb4b4b4:Te6edf3hrefTff7b72=Ta5d6ff"Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/attachment/Tffd700${Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTffd700}Ta5d6ff/file?file_index=Tffd700${Te6edf3indexTffd700}Ta5d6ff`Ta5d6ff"
Te6edf3classTff7b72=Ta5d6ff"flex items-center gap-3 border rounded-lg px-3 py-2 text-sm font-medium cursor-pointer transition-colors"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3is_outbound
Tff7b72? Ta5d6ff'bg-white/20 text-white border-white/20 hover:bg-white/30'
Tff7b72: Ta5d6ff'bg-gray-50 dark:bg-zinc-800/50 text-gray-700 dark:text-zinc-300 border-gray-200/60 dark:border-zinc-700 hover:bg-gray-100 dark:hover:bg-zinc-800'
Ta5d6ff"
@Te6edf3click.Te6edf3stop
Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-6 h-6"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13"
Tb4b4b4>Tb4b4b4<Tb4b4b4/Tff7b72pathTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"flex-1 min-w-0"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"truncate"Tb4b4b4>Tff7b72{{ Te6edf3file_attachmentTb4b4b4.Te6edf3file_name Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"text-xs font-normal mt-0.5"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3is_outbound
Tff7b72? Ta5d6ff'text-white/60'
Tff7b72: Ta5d6ff'text-gray-500 dark:text-zinc-400'
Ta5d6ff"
Tb4b4b4>
Tff7b72{{ Te6edf3formatAttachmentSizeTb4b4b4(Te6edf3file_attachmentTb4b4b4, Ta5d6ff"file"Tb4b4b4) Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-6 h-6"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72aTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- telemetry / location field -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3telemetryTff7b72?Tb4b4b4.Te6edf3locationTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"pb-1 mt-1"Tb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"flex items-center gap-2 border border-gray-200/60 dark:border-zinc-700 hover:bg-gray-50 dark:hover:bg-zinc-800 rounded-lg px-3 py-2 text-sm font-medium transition-colors"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3is_outbound
Tff7b72? Ta5d6ff'bg-white/20 text-white border-white/20 hover:bg-white/30'
Tff7b72: Ta5d6ff'bg-gray-50 dark:bg-zinc-800/50 text-gray-700 dark:text-zinc-300'
Ta5d6ff"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3viewLocationOnMapTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3telemetryTb4b4b4.Te6edf3locationTb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"map-marker" Te6edf3classTff7b72=Ta5d6ff"size-5" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"text-left"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"font-bold text-xs uppercase tracking-wider opacity-80"Tb4b4b4>
Location
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"text-[10px] font-mono opacity-70"Tb4b4b4>
Tff7b72{{ Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3telemetryTb4b4b4.Te6edf3locationTb4b4b4.Te6edf3latitudeTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff6Tb4b4b4) Tff7b72}},
Tff7b72{{ Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3telemetryTb4b4b4.Te6edf3locationTb4b4b4.Te6edf3longitudeTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff6Tb4b4b4) Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- actions -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3is_actions_expandedTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"border-t px-4 py-2.5"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3is_outbound
Tff7b72? Ta5d6ff'border-white/20 bg-white/10'
Tff7b72: Ta5d6ff'border-gray-200/60 dark:border-zinc-800/60 bg-gray-50/50 dark:bg-zinc-900/50'
Ta5d6ff"
Tb4b4b4>
T8b949e<!-- delete message -->
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"inline-flex items-center gap-x-1.5 rounded-lg bg-red-500 px-3 py-1.5 text-xs font-semibold text-white shadow-sm hover:bg-red-600 transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
Tb4b4b4@Te6edf3clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"Te6edf3deleteChatItemTb4b4b4(Te6edf3chatItemTb4b4b4)Ta5d6ff"
Tb4b4b4>
Delete
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- message state -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3is_outboundTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"flex text-right mt-1.5 px-1"
Tb4b4b4:Te6edf3classTff7b72=Ta5d6ff"Tb4b4b4[
Tb4b4b4[Ta5d6ff'cancelled'Tb4b4b4, Ta5d6ff'failed'Tb4b4b4]Tb4b4b4.Te6edf3includesTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3stateTb4b4b4)
Tff7b72? Ta5d6ff'text-red-500 dark:text-red-400'
Tff7b72: Ta5d6ff'text-gray-400 dark:text-zinc-500'Tb4b4b4,
Tb4b4b4]Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"flex ml-auto items-center space-x-1.5 text-xs"Tb4b4b4>
T8b949e<!-- state label -->
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72span
Te6edf3classTff7b72=Ta5d6ff"space-x-1 cursor-pointer hover:underline"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3toggleSentMessageInfoTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Tff7b72{{ Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72span
Te6edf3v-ifTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'outbound' Tff7b72&&
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3delivery_attempts Tff7b72>= T79c0ff1
Ta5d6ff"
Tb4b4b4>(attempt Tff7b72{{ Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3delivery_attempts Tff7b72+ T79c0ff1 Tff7b72}})Tb4b4b4<Tb4b4b4/Tff7b72span
Tb4b4b4>
Tb4b4b4<Tff7b72span
Te6edf3v-ifTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'sent' Tff7b72&&
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3method Tff7b72=== Ta5d6ff'opportunistic' Tff7b72&&
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3delivery_attempts Tff7b72>= T79c0ff1
Ta5d6ff"
Tb4b4b4>(attempt Tff7b72{{ Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3delivery_attempts Tff7b72}})Tb4b4b4<Tb4b4b4/Tff7b72span
Tb4b4b4>
Tb4b4b4<Tff7b72span
Te6edf3v-ifTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'sent' Tff7b72&&
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3method Tff7b72=== Ta5d6ff'propagated'
Ta5d6ff"
Tb4b4b4>to propagation nodeTb4b4b4<Tb4b4b4/Tff7b72span
Tb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'sending'Ta5d6ff"
Tb4b4b4>Tff7b72{{ Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3progressTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff0Tb4b4b4) Tff7b72}}%Tb4b4b4<Tb4b4b4/Tff7b72span
Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tff7b72a
Te6edf3v-ifTff7b72=Ta5d6ff"
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'outbound' Tff7b72||
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'sending' Tff7b72||
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'sent'
Ta5d6ff"
Te6edf3classTff7b72=Ta5d6ff"ml-1 cursor-pointer underline text-blue-500"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3cancelSendingMessageTb4b4b4(Te6edf3chatItemTb4b4b4)Ta5d6ff"
Tb4b4b4>cancel?Tb4b4b4<Tb4b4b4/Tff7b72a
Tb4b4b4>
Tb4b4b4<Tff7b72a
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'failed'Ta5d6ff"
Te6edf3classTff7b72=Ta5d6ff"ml-1 cursor-pointer underline text-blue-500"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3retrySendingMessageTb4b4b4(Te6edf3chatItemTb4b4b4)Ta5d6ff"
Tb4b4b4>retry?Tb4b4b4<Tb4b4b4/Tff7b72a
Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- delivered icon -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'delivered'Ta5d6ff" Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3fillTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-5 h-5"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3fill-ruleTff7b72=Ta5d6ff"evenodd"
Te6edf3dTff7b72=Ta5d6ff"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z"
Te6edf3clip-ruleTff7b72=Ta5d6ff"evenodd"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- cancelled icon -->
Tb4b4b4<Tff7b72div Te6edf3v-else-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'cancelled'Ta5d6ff" Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3fillTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"size-5"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3fill-ruleTff7b72=Ta5d6ff"evenodd"
Te6edf3dTff7b72=Ta5d6ff"M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25Zm-1.72 6.97a.75.75 0 1 0-1.06 1.06L10.94 12l-1.72 1.72a.75.75 0 1 0 1.06 1.06L12 13.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L13.06 12l1.72-1.72a.75.75 0 1 0-1.06-1.06L12 10.94l-1.72-1.72Z"
Te6edf3clip-ruleTff7b72=Ta5d6ff"evenodd"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- failed icon -->
Tb4b4b4<Tff7b72div Te6edf3v-else-ifTff7b72=Ta5d6ff"Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'failed'Ta5d6ff" Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3fillTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-5 h-5"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3fill-ruleTff7b72=Ta5d6ff"evenodd"
Te6edf3dTff7b72=Ta5d6ff"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75Zm0 8.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
Te6edf3clip-ruleTff7b72=Ta5d6ff"evenodd"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- fallback icon -->
Tb4b4b4<Tff7b72div Te6edf3v-else Te6edf3classTff7b72=Ta5d6ff"my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-5 h-5"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"M8.625 12a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- inbound message info -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Tff7b72!Te6edf3chatItemTb4b4b4.Te6edf3is_outboundTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"text-xs text-gray-400 dark:text-zinc-500 mt-1.5 px-1 flex flex-col"
Tb4b4b4>
T8b949e<!-- received timestamp -->
Tb4b4b4<Tff7b72span
Te6edf3classTff7b72=Ta5d6ff"cursor-pointer hover:underline"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3toggleReceivedMessageInfoTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4)Ta5d6ff"
Tb4b4b4>Tff7b72{{ Te6edf3formatTimeAgoTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3created_atTb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72span
Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- expanded message details -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3expandedMessageInfo Tff7b72=== Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"mt-2 px-1 text-xs text-gray-500 dark:text-zinc-400 space-y-0.5"
Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3v-forTff7b72=Ta5d6ff"Tb4b4b4(Te6edf3lineTb4b4b4, Te6edf3indexTb4b4b4) Tff7b72in Te6edf3getMessageInfoLinesTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4, Te6edf3chatItemTb4b4b4.Te6edf3is_outboundTb4b4b4)Ta5d6ff"
Tb4b4b4:Te6edf3keyTff7b72=Ta5d6ff"Te6edf3indexTa5d6ff"
Tb4b4b4>
Tff7b72{{ Te6edf3line Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- load previous -->
Tb4b4b4<Tff7b72button
Te6edf3v-showTff7b72=Ta5d6ff"Tff7b72!Te6edf3isLoadingPrevious Tff7b72&& Te6edf3hasMorePreviousTa5d6ff"
Te6edf3idTff7b72=Ta5d6ff"load-previous"
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"flex items-center gap-2 mx-auto mt-4 bg-white dark:bg-zinc-900 border border-gray-200 dark:border-zinc-800 px-4 py-2 hover:bg-gray-50 dark:hover:bg-zinc-800 rounded-full shadow-sm text-sm font-medium text-gray-700 dark:text-zinc-300 transition-colors"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3loadPreviousTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-4 h-4"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"m15 11.25-3-3m0 0-3 3m3-3v7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Load PreviousTb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- send message -->
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"w-full border-t border-gray-200/60 dark:border-zinc-800/60 bg-white/80 dark:bg-zinc-900/50 backdrop-blur-sm px-3 sm:px-4 py-2.5"
Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"w-full"Tb4b4b4>
T8b949e<!-- blocked user notification -->
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3isSelectedPeerBlockedTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"mb-3 p-3 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg flex items-center gap-2"
Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"2"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-5 h-5 text-yellow-600 dark:text-yellow-400 flex-shrink-0"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3classTff7b72=Ta5d6ff"text-sm text-yellow-800 dark:text-yellow-200"
Tb4b4b4>You have blocked this user. They cannot send you messages or establish links.Tb4b4b4<Tb4b4b4/Tff7b72span
Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- message composer -->
Tb4b4b4<Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"space-y-2"Tb4b4b4>
T8b949e<!-- image attachment -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3newMessageImageTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"attachment-card"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"attachment-card__preview" Tb4b4b4@Te6edf3clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"Te6edf3openImageTb4b4b4(Te6edf3newMessageImageUrlTb4b4b4)Ta5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72img
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3newMessageImageUrlTa5d6ff"
Tb4b4b4:Te6edf3srcTff7b72=Ta5d6ff"Te6edf3newMessageImageUrlTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"w-full h-full object-cover rounded-lg"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"attachment-card__body"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"attachment-card__title"Tb4b4b4>Image AttachmentTb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"attachment-card__meta"Tb4b4b4>Tff7b72{{ Te6edf3formatBytesTb4b4b4(Te6edf3newMessageImageTb4b4b4.Te6edf3sizeTb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72button Te6edf3typeTff7b72=Ta5d6ff"button" Te6edf3classTff7b72=Ta5d6ff"attachment-card__remove" Tb4b4b4@Te6edf3clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"Te6edf3removeImageAttachmentTa5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"close" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- audio attachment -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3newMessageAudioTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"attachment-card"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"attachment-card__body w-full"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"attachment-card__title"Tb4b4b4>Voice NoteTb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"attachment-card__meta"Tb4b4b4>
Tff7b72{{ Te6edf3formatBytesTb4b4b4(Te6edf3newMessageAudioTb4b4b4.Te6edf3audio_blobTb4b4b4.Te6edf3sizeTb4b4b4) Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72audio
Te6edf3controls
Te6edf3classTff7b72=Ta5d6ff"w-full mt-2 rounded-lg shadow-sm audio-controls-dark"
Te6edf3styleTff7b72=Ta5d6ff"height: 54px"
Tb4b4b4>
Tb4b4b4<Tff7b72source Tb4b4b4:Te6edf3srcTff7b72=Ta5d6ff"Te6edf3newMessageAudioTb4b4b4.Te6edf3audio_preview_urlTa5d6ff" Te6edf3typeTff7b72=Ta5d6ff"audio/wav" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72audioTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72button Te6edf3typeTff7b72=Ta5d6ff"button" Te6edf3classTff7b72=Ta5d6ff"attachment-card__remove" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3removeAudioAttachmentTa5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"delete" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- file attachments -->
Tb4b4b4<Tff7b72div Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3newMessageFilesTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Ta5d6ff" Te6edf3classTff7b72=Ta5d6ff"flex flex-wrap gap-2"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3v-forTff7b72=Ta5d6ff"Te6edf3file Tff7b72in Te6edf3newMessageFilesTa5d6ff" Tb4b4b4:Te6edf3keyTff7b72=Ta5d6ff"Te6edf3fileTb4b4b4.Te6edf3name Tff7b72+ Te6edf3fileTb4b4b4.Te6edf3sizeTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"attachment-chip"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"flex items-center gap-2"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon
Te6edf3icon-nameTff7b72=Ta5d6ff"paperclip"
Te6edf3classTff7b72=Ta5d6ff"w-4 h-4 text-gray-500 dark:text-gray-300"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"text-sm text-gray-800 dark:text-gray-200 truncate max-w-[160px]"Tb4b4b4>
Tff7b72{{ Te6edf3fileTb4b4b4.Te6edf3name Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72span Te6edf3classTff7b72=Ta5d6ff"text-xs text-gray-500 dark:text-gray-400"Tb4b4b4>Tff7b72{{
Te6edf3formatBytesTb4b4b4(Te6edf3fileTb4b4b4.Te6edf3sizeTb4b4b4)
Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"attachment-chip__remove"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3removeFileAttachmentTb4b4b4(Te6edf3fileTb4b4b4)Ta5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"close" Te6edf3classTff7b72=Ta5d6ff"w-3.5 h-3.5" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- text input -->
Tb4b4b4<Tff7b72textarea
Te6edf3idTff7b72=Ta5d6ff"message-input"
Te6edf3refTff7b72=Ta5d6ff"message-input"
Te6edf3v-modelTff7b72=Ta5d6ff"Te6edf3newMessageTextTa5d6ff"
Tb4b4b4:Te6edf3readonlyTff7b72=Ta5d6ff"Te6edf3isSendingMessageTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"bg-white dark:bg-zinc-900 border border-gray-200 dark:border-zinc-800 text-gray-900 dark:text-zinc-100 text-sm rounded-xl focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500 block w-full px-3 sm:px-4 py-2 resize-none shadow-sm transition-all placeholder:text-gray-400 dark:placeholder:text-zinc-500"
Te6edf3rowsTff7b72=Ta5d6ff"2"
Tb4b4b4:Te6edf3placeholderTff7b72=Ta5d6ff"Te6edf3$tTb4b4b4(Ta5d6ff'messages.send_placeholder'Tb4b4b4)Ta5d6ff"
Tb4b4b4@Te6edf3keydownTb4b4b4.Te6edf3enterTb4b4b4.Te6edf3exactTb4b4b4.Te6edf3preventTff7b72=Ta5d6ff"Te6edf3onEnterPressedTa5d6ff"
Tb4b4b4@Te6edf3keydownTb4b4b4.Te6edf3enterTb4b4b4.Te6edf3shiftTb4b4b4.Te6edf3exactTb4b4b4.Te6edf3preventTff7b72=Ta5d6ff"Te6edf3onShiftEnterPressedTa5d6ff"
Tb4b4b4>Tb4b4b4<Tb4b4b4/Tff7b72textareaTb4b4b4>
T8b949e<!-- action button -->
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"flex flex-wrap gap-2 items-center mt-2"Tb4b4b4>
Tb4b4b4<Tff7b72button Te6edf3typeTff7b72=Ta5d6ff"button" Te6edf3classTff7b72=Ta5d6ff"attachment-action-button" Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3addFilesToMessageTa5d6ff"Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"paperclip-plus" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Tff7b72{{ Te6edf3$tTb4b4b4(Ta5d6ff"messages.add_files"Tb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tff7b72AddImageButton Tb4b4b4@Te6edf3add-imageTff7b72=Ta5d6ff"Te6edf3onImageSelectedTa5d6ff" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72AddAudioButton
Tb4b4b4:Te6edf3is-recording-audio-attachmentTff7b72=Ta5d6ff"Te6edf3isRecordingAudioAttachmentTa5d6ff"
Tb4b4b4@Te6edf3start-recordingTff7b72=Ta5d6ff"Te6edf3startRecordingAudioAttachmentTb4b4b4(Te6edf3$eventTb4b4b4)Ta5d6ff"
Tb4b4b4@Te6edf3stop-recordingTff7b72=Ta5d6ff"Te6edf3stopRecordingAudioAttachmentTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Tff7b72{{ Te6edf3$tTb4b4b4(Ta5d6ff"messages.recording"Tb4b4b4, Tb4b4b4{ Te6edf3durationTff7b72: Te6edf3audioAttachmentRecordingDuration Tb4b4b4}Tb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72AddAudioButtonTb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"attachment-action-button"
Tb4b4b4:Te6edf3titleTff7b72=Ta5d6ff"Te6edf3$tTb4b4b4(Ta5d6ff'messages.share_location'Tb4b4b4)Ta5d6ff"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3shareLocationTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"map-marker" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Tff7b72{{ Te6edf3$tTb4b4b4(Ta5d6ff"messages.location"Tb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"attachment-action-button"
Tb4b4b4:Te6edf3titleTff7b72=Ta5d6ff"Te6edf3$tTb4b4b4(Ta5d6ff'messages.request_location'Tb4b4b4)Ta5d6ff"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3requestLocationTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72MaterialDesignIcon Te6edf3icon-nameTff7b72=Ta5d6ff"crosshairs-question" Te6edf3classTff7b72=Ta5d6ff"w-4 h-4" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tff7b72spanTb4b4b4>Tff7b72{{ Te6edf3$tTb4b4b4(Ta5d6ff"messages.request"Tb4b4b4) Tff7b72}}Tb4b4b4<Tb4b4b4/Tff7b72spanTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"ml-auto my-auto"Tb4b4b4>
Tb4b4b4<Tff7b72SendMessageButton
Tb4b4b4:Te6edf3is-sending-messageTff7b72=Ta5d6ff"Te6edf3isSendingMessageTa5d6ff"
Tb4b4b4:Te6edf3can-send-messageTff7b72=Ta5d6ff"Te6edf3canSendMessageTa5d6ff"
Tb4b4b4:Te6edf3delivery-methodTff7b72=Ta5d6ff"Te6edf3newMessageDeliveryMethodTa5d6ff"
Tb4b4b4@Te6edf3sendTff7b72=Ta5d6ff"Te6edf3sendMessageTa5d6ff"
Tb4b4b4@Te6edf3delivery-method-changedTff7b72=Ta5d6ff"Te6edf3newMessageDeliveryMethod Tff7b72= Te6edf3$eventTa5d6ff"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- hidden file input for selecting files -->
Tb4b4b4<Tff7b72input Te6edf3refTff7b72=Ta5d6ff"file-input" Te6edf3typeTff7b72=Ta5d6ff"file" Te6edf3multiple Te6edf3styleTff7b72=Ta5d6ff"display: none" Tb4b4b4@Te6edf3changeTff7b72=Ta5d6ff"Te6edf3onFileInputChangeTa5d6ff" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- no peer selected -->
Tb4b4b4<Tff7b72div Te6edf3v-else Te6edf3classTff7b72=Ta5d6ff"flex flex-col h-full items-center justify-center"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"w-full max-w-md px-4"Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"mb-6 text-center"Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3classTff7b72=Ta5d6ff"w-16 h-16 mx-auto mb-4 rounded-2xl bg-gradient-to-br from-blue-100 to-blue-200 dark:from-blue-900/30 dark:to-blue-800/30 flex items-center justify-center"
Tb4b4b4>
Tb4b4b4<Tff7b72svg
Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg"
Te6edf3fillTff7b72=Ta5d6ff"none"
Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 24 24"
Te6edf3stroke-widthTff7b72=Ta5d6ff"1.5"
Te6edf3strokeTff7b72=Ta5d6ff"currentColor"
Te6edf3classTff7b72=Ta5d6ff"w-8 h-8 text-blue-600 dark:text-blue-400"
Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3stroke-linecapTff7b72=Ta5d6ff"round"
Te6edf3stroke-linejoinTff7b72=Ta5d6ff"round"
Te6edf3dTff7b72=Ta5d6ff"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72h3 Te6edf3classTff7b72=Ta5d6ff"text-lg font-semibold text-gray-900 dark:text-zinc-100 mb-1"Tb4b4b4>
Tff7b72{{ Te6edf3$tTb4b4b4(Ta5d6ff"messages.no_active_chat"Tb4b4b4) Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72h3Tb4b4b4>
Tb4b4b4<Tff7b72p Te6edf3classTff7b72=Ta5d6ff"text-sm text-gray-500 dark:text-zinc-400"Tb4b4b4>
Tff7b72{{ Te6edf3$tTb4b4b4(Ta5d6ff"messages.select_peer_or_enter_address"Tb4b4b4) Tff7b72}}
Tb4b4b4<Tb4b4b4/Tff7b72pTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- compose message input -->
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"w-full"Tb4b4b4>
Tb4b4b4<Tff7b72input
Te6edf3idTff7b72=Ta5d6ff"compose-input"
Te6edf3refTff7b72=Ta5d6ff"compose-input"
Te6edf3v-modelTff7b72=Ta5d6ff"Te6edf3composeAddressTa5d6ff"
Tb4b4b4:Te6edf3readonlyTff7b72=Ta5d6ff"Te6edf3isSendingMessageTa5d6ff"
Te6edf3typeTff7b72=Ta5d6ff"text"
Te6edf3classTff7b72=Ta5d6ff"w-full bg-white dark:bg-zinc-900 border border-gray-200 dark:border-zinc-800 text-gray-900 dark:text-zinc-100 text-sm rounded-xl focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500 px-4 py-2.5 shadow-sm transition-all placeholder:text-gray-400 dark:placeholder:text-zinc-500"
Te6edf3placeholderTff7b72=Ta5d6ff"Enter LXMF address..."
Tb4b4b4@Te6edf3keydownTb4b4b4.Te6edf3enterTb4b4b4.Te6edf3exactTb4b4b4.Te6edf3preventTff7b72=Ta5d6ff"Te6edf3onComposeEnterPressedTa5d6ff"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
T8b949e<!-- image modal -->
Tb4b4b4<Tff7b72Transition
Te6edf3enter-active-classTff7b72=Ta5d6ff"transition ease-out duration-200"
Te6edf3enter-from-classTff7b72=Ta5d6ff"opacity-0"
Te6edf3enter-to-classTff7b72=Ta5d6ff"opacity-100"
Te6edf3leave-active-classTff7b72=Ta5d6ff"transition ease-in duration-150"
Te6edf3leave-from-classTff7b72=Ta5d6ff"opacity-100"
Te6edf3leave-to-classTff7b72=Ta5d6ff"opacity-0"
Tb4b4b4>
Tb4b4b4<Tff7b72div
Te6edf3v-ifTff7b72=Ta5d6ff"Te6edf3imageModalUrlTa5d6ff"
Te6edf3classTff7b72=Ta5d6ff"fixed inset-0 z-50 flex items-center justify-center bg-black/80 dark:bg-black/90 backdrop-blur-sm p-4"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3closeImageModalTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3classTff7b72=Ta5d6ff"relative max-w-7xl max-h-full" @Te6edf3click.Te6edf3stopTb4b4b4>
Tb4b4b4<Tff7b72button
Te6edf3typeTff7b72=Ta5d6ff"button"
Te6edf3classTff7b72=Ta5d6ff"absolute -top-12 right-0 inline-flex items-center justify-center w-10 h-10 rounded-xl bg-white/10 dark:bg-zinc-900/10 hover:bg-white/20 dark:hover:bg-zinc-900/20 text-white transition-colors"
Tb4b4b4@Te6edf3clickTff7b72=Ta5d6ff"Te6edf3closeImageModalTa5d6ff"
Tb4b4b4>
Tb4b4b4<Tff7b72svg Te6edf3xmlnsTff7b72=Ta5d6ff"http://www.w3.org/2000/svg" Te6edf3viewBoxTff7b72=Ta5d6ff"0 0 20 20" Te6edf3fillTff7b72=Ta5d6ff"currentColor" Te6edf3classTff7b72=Ta5d6ff"w-5 h-5"Tb4b4b4>
Tb4b4b4<Tff7b72path
Te6edf3dTff7b72=Ta5d6ff"M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z"
Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72svgTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72buttonTb4b4b4>
Tb4b4b4<Tff7b72img Tb4b4b4:Te6edf3srcTff7b72=Ta5d6ff"Te6edf3imageModalUrlTa5d6ff" Te6edf3classTff7b72=Ta5d6ff"max-w-full max-h-[90vh] rounded-xl shadow-2xl" Te6edf3altTff7b72=Ta5d6ff"Image preview" Tb4b4b4/Tb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72TransitionTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72templateTb4b4b4>
Tb4b4b4<Tff7b72scriptTb4b4b4>
Tff7b72import Te6edf3Utils Tff7b72from Ta5d6ff"../../js/Utils"Tb4b4b4;
Tff7b72import Te6edf3DialogUtils Tff7b72from Ta5d6ff"../../js/DialogUtils"Tb4b4b4;
Tff7b72import Te6edf3MicrophoneRecorder Tff7b72from Ta5d6ff"../../js/MicrophoneRecorder"Tb4b4b4;
Tff7b72import Te6edf3NotificationUtils Tff7b72from Ta5d6ff"../../js/NotificationUtils"Tb4b4b4;
Tff7b72import Te6edf3WebSocketConnection Tff7b72from Ta5d6ff"../../js/WebSocketConnection"Tb4b4b4;
Tff7b72import Te6edf3AddAudioButton Tff7b72from Ta5d6ff"./AddAudioButton.vue"Tb4b4b4;
Tff7b72import Te6edf3dayjs Tff7b72from Ta5d6ff"dayjs"Tb4b4b4;
Tff7b72import Te6edf3relativeTime Tff7b72from Ta5d6ff"dayjs/plugin/relativeTime"Tb4b4b4;
Te6edf3dayjsTb4b4b4.Te6edf3extendTb4b4b4(Te6edf3relativeTimeTb4b4b4)Tb4b4b4;
Tff7b72import Te6edf3SendMessageButton Tff7b72from Ta5d6ff"./SendMessageButton.vue"Tb4b4b4;
Tff7b72import Te6edf3MaterialDesignIcon Tff7b72from Ta5d6ff"../MaterialDesignIcon.vue"Tb4b4b4;
Tff7b72import Te6edf3ConversationDropDownMenu Tff7b72from Ta5d6ff"./ConversationDropDownMenu.vue"Tb4b4b4;
Tff7b72import Te6edf3AddImageButton Tff7b72from Ta5d6ff"./AddImageButton.vue"Tb4b4b4;
Tff7b72import Te6edf3IconButton Tff7b72from Ta5d6ff"../IconButton.vue"Tb4b4b4;
Tff7b72import Te6edf3GlobalEmitter Tff7b72from Ta5d6ff"../../js/GlobalEmitter"Tb4b4b4;
Tff7b72import Te6edf3ToastUtils Tff7b72from Ta5d6ff"../../js/ToastUtils"Tb4b4b4;
Tff7b72export Tff7b72default Tb4b4b4{
Te6edf3nameTff7b72: Ta5d6ff"ConversationViewer"Tb4b4b4,
Te6edf3componentsTff7b72: Tb4b4b4{
Te6edf3IconButtonTb4b4b4,
Te6edf3AddImageButtonTb4b4b4,
Te6edf3ConversationDropDownMenuTb4b4b4,
Te6edf3MaterialDesignIconTb4b4b4,
Te6edf3SendMessageButtonTb4b4b4,
Te6edf3AddAudioButtonTb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3propsTff7b72: Tb4b4b4{
Te6edf3myLxmfAddressHashTff7b72: Tb4b4b4{
Te6edf3typeTff7b72: Tffa657StringTb4b4b4,
Te6edf3requiredTff7b72: Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3selectedPeerTff7b72: Tb4b4b4{
Te6edf3typeTff7b72: Tffa657ObjectTb4b4b4,
Te6edf3requiredTff7b72: Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3conversationsTff7b72: Tb4b4b4{
Te6edf3typeTff7b72: Tffa657ArrayTb4b4b4,
Te6edf3requiredTff7b72: Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3emitsTff7b72: Tb4b4b4[Ta5d6ff"close"Tb4b4b4, Ta5d6ff"reload-conversations"Tb4b4b4, Ta5d6ff"update:selectedPeer"Tb4b4b4]Tb4b4b4,
Te6edf3dataTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3selectedPeerPathTff7b72: Tff7b72nullTb4b4b4,
Te6edf3selectedPeerLxmfStampInfoTff7b72: Tff7b72nullTb4b4b4,
Te6edf3selectedPeerSignalMetricsTff7b72: Tff7b72nullTb4b4b4,
Te6edf3lxmfMessagesRequestSequenceTff7b72: T79c0ff0Tb4b4b4,
Te6edf3chatItemsTff7b72: Tb4b4b4[Tb4b4b4]Tb4b4b4,
Te6edf3isLoadingPreviousTff7b72: Tff7b72falseTb4b4b4,
Te6edf3hasMorePreviousTff7b72: Tff7b72trueTb4b4b4,
Te6edf3newMessageDeliveryMethodTff7b72: Tff7b72nullTb4b4b4,
Te6edf3newMessageTextTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3newMessageImageTff7b72: Tff7b72nullTb4b4b4,
Te6edf3newMessageImageUrlTff7b72: Tff7b72nullTb4b4b4,
Te6edf3newMessageAudioTff7b72: Tff7b72nullTb4b4b4,
Te6edf3newMessageTelemetryTff7b72: Tff7b72nullTb4b4b4,
Te6edf3newMessageFilesTff7b72: Tb4b4b4[Tb4b4b4]Tb4b4b4,
Te6edf3isSendingMessageTff7b72: Tff7b72falseTb4b4b4,
Te6edf3autoScrollOnNewMessageTff7b72: Tff7b72trueTb4b4b4,
Te6edf3composeAddressTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3isShareContactModalOpenTff7b72: Tff7b72falseTb4b4b4,
Te6edf3contactsTff7b72: Tb4b4b4[Tb4b4b4]Tb4b4b4,
Te6edf3contactsSearchTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3isRecordingAudioAttachmentTff7b72: Tff7b72falseTb4b4b4,
Te6edf3audioAttachmentMicrophoneRecorderTff7b72: Tff7b72nullTb4b4b4,
Te6edf3audioAttachmentMicrophoneRecorderCodecTff7b72: Tff7b72nullTb4b4b4,
Te6edf3audioAttachmentRecordingStartedAtTff7b72: Tff7b72nullTb4b4b4,
Te6edf3audioAttachmentRecordingDurationTff7b72: Tff7b72nullTb4b4b4,
Te6edf3audioAttachmentRecordingTimerTff7b72: Tff7b72nullTb4b4b4,
Te6edf3lxmfMessageAudioAttachmentCacheTff7b72: Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3isDownloadingAudioTff7b72: Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3expandedMessageInfoTff7b72: Tff7b72nullTb4b4b4,
Te6edf3imageModalUrlTff7b72: Tff7b72nullTb4b4b4,
Te6edf3isSelectedPeerBlockedTff7b72: Tff7b72falseTb4b4b4,
Te6edf3blockedDestinationsTff7b72: Tb4b4b4[Tb4b4b4]Tb4b4b4,
Te6edf3lxmfAudioModeToCodec2ModeMapTff7b72: Tb4b4b4{
T8b949e// https://github.com/markqvist/LXMF/blob/master/LXMF/LXMF.py#L21
T79c0ff0x01Tff7b72: Ta5d6ff"450PWB"Tb4b4b4, T8b949e// AM_CODEC2_450PWB
T79c0ff0x02Tff7b72: Ta5d6ff"450"Tb4b4b4, T8b949e// AM_CODEC2_450
T79c0ff0x03Tff7b72: Ta5d6ff"700C"Tb4b4b4, T8b949e// AM_CODEC2_700C
T79c0ff0x04Tff7b72: Ta5d6ff"1200"Tb4b4b4, T8b949e// AM_CODEC2_1200
T79c0ff0x05Tff7b72: Ta5d6ff"1300"Tb4b4b4, T8b949e// AM_CODEC2_1300
T79c0ff0x06Tff7b72: Ta5d6ff"1400"Tb4b4b4, T8b949e// AM_CODEC2_1400
T79c0ff0x07Tff7b72: Ta5d6ff"1600"Tb4b4b4, T8b949e// AM_CODEC2_1600
T79c0ff0x08Tff7b72: Ta5d6ff"2400"Tb4b4b4, T8b949e// AM_CODEC2_2400
T79c0ff0x09Tff7b72: Ta5d6ff"3200"Tb4b4b4, T8b949e// AM_CODEC2_3200
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3computedTff7b72: Tb4b4b4{
Te6edf3filteredContactsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3contactsSearchTb4b4b4) Tff7b72return Tff7b72thisTb4b4b4.Te6edf3contactsTb4b4b4;
Tff7b72const Te6edf3s Tff7b72= Tff7b72thisTb4b4b4.Te6edf3contactsSearchTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3contactsTb4b4b4.Te6edf3filterTb4b4b4(
Tb4b4b4(Te6edf3cTb4b4b4) Tb4b4b4=> Te6edf3cTb4b4b4.Te6edf3nameTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3includesTb4b4b4(Te6edf3sTb4b4b4) Tff7b72|| Te6edf3cTb4b4b4.Te6edf3remote_identity_hashTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3includesTb4b4b4(Te6edf3sTb4b4b4)
Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3isMobileTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Ta5d6ff/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3navigatorTb4b4b4.Te6edf3userAgentTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3canSendMessageTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// can't send if empty message
Tff7b72const Te6edf3messageText Tff7b72= Tff7b72thisTb4b4b4.Te6edf3newMessageTextTb4b4b4.Te6edf3trimTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3messageText Tff7b72== Tff7b72null Tff7b72|| Te6edf3messageText Tff7b72=== Ta5d6ff""Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4}
T8b949e// can't send if already sending
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3isSendingMessageTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3selectedPeerChatItemsTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// get all chat items related to the selected peer
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3filterTb4b4b4(Tb4b4b4(Te6edf3chatItemTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3type Tff7b72=== Ta5d6ff"lxmf_message"Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3isFromSelectedPeer Tff7b72=
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3source_hash Tff7b72=== Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTb4b4b4;
Tff7b72const Te6edf3isToSelectedPeer Tff7b72=
Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3destination_hash Tff7b72=== Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTb4b4b4;
Tff7b72return Te6edf3isFromSelectedPeer Tff7b72|| Te6edf3isToSelectedPeerTb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// no peer, so no chat items!
Tff7b72return Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3selectedPeerChatItemsReversedTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// ensure a copy of the array is returned in reverse order
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3selectedPeerChatItemsTb4b4b4.Te6edf3mapTb4b4b4(Tb4b4b4(Te6edf3messageTb4b4b4) Tb4b4b4=> Te6edf3messageTb4b4b4)Tb4b4b4.Te6edf3reverseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3oldestMessageIdTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3selectedPeerChatItemsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3selectedPeerChatItemsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3idTb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3watchTff7b72: Tb4b4b4{
Te6edf3selectedPeerTff7b72: Tb4b4b4{
Te6edf3handlerTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3checkIfSelectedPeerBlockedTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3initialLoadTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3immediateTff7b72: Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3selectedPeerChatItemsTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// chat items for selected peer changed, so lets process any available audio
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3processAudioForSelectedPeerChatItemsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3beforeUnmountTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// stop listening for websocket messages
Te6edf3WebSocketConnectionTb4b4b4.Te6edf3offTb4b4b4(Ta5d6ff"message"Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3onWebsocketMessageTb4b4b4)Tb4b4b4;
Te6edf3GlobalEmitterTb4b4b4.Te6edf3offTb4b4b4(Ta5d6ff"compose-new-message"Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3onComposeNewMessageEventTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3mountedTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// listen for websocket messages
Te6edf3WebSocketConnectionTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"message"Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3onWebsocketMessageTb4b4b4)Tb4b4b4;
T8b949e// listen for compose new message event
Te6edf3GlobalEmitterTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"compose-new-message"Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3onComposeNewMessageEventTb4b4b4)Tb4b4b4;
T8b949e// load blocked destinations
Tff7b72thisTb4b4b4.Te6edf3loadBlockedDestinationsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3methodsTff7b72: Tb4b4b4{
Tff7b72async Te6edf3loadBlockedDestinationsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(Ta5d6ff"/api/v1/blocked-destinations"Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3blockedDestinations Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3blocked_destinations Tff7b72|| Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3checkIfSelectedPeerBlockedTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3checkIfSelectedPeerBlockedTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3isSelectedPeerBlocked Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3isSelectedPeerBlocked Tff7b72= Tff7b72thisTb4b4b4.Te6edf3blockedDestinationsTb4b4b4.Te6edf3someTb4b4b4(
Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3destination_hash Tff7b72=== Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hash
Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3closeTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3$emitTb4b4b4(Ta5d6ff"close"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onMessagesScrollTb4b4b4(Te6edf3eventTb4b4b4) Tb4b4b4{
T8b949e// check if messages is scrolled to bottom
Tff7b72const Te6edf3element Tff7b72= Te6edf3eventTb4b4b4.Te6edf3targetTb4b4b4;
Tff7b72const Te6edf3isAtBottom Tff7b72= Te6edf3elementTb4b4b4.Te6edf3scrollTop Tff7b72=== Te6edf3elementTb4b4b4.Te6edf3scrollHeight Tff7b72- Te6edf3elementTb4b4b4.Te6edf3offsetHeightTb4b4b4;
T8b949e// we want to auto scroll if user is at bottom of messages list
Tff7b72thisTb4b4b4.Te6edf3autoScrollOnNewMessage Tff7b72= Te6edf3isAtBottomTb4b4b4;
T8b949e// load previous when scrolling near top of page
Tff7b72if Tb4b4b4(Te6edf3elementTb4b4b4.Te6edf3scrollTop Tff7b72<= T79c0ff500Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3loadPreviousTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3initialLoadTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// reset
Tff7b72thisTb4b4b4.Te6edf3chatItems Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3hasMorePrevious Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3selectedPeerPath Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3selectedPeerLxmfStampInfo Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3selectedPeerSignalMetrics Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3getPeerPathTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3getPeerLxmfStampInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3getPeerSignalMetricsTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// load 1 page of previous messages
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3loadPreviousTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// scroll to bottom
Tff7b72thisTb4b4b4.Te6edf3scrollMessagesToBottomTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3loadPreviousTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// do nothing if already loading
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3isLoadingPreviousTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3isLoadingPrevious Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3seq Tff7b72= Tff7b72++Tff7b72thisTb4b4b4.Te6edf3lxmfMessagesRequestSequenceTb4b4b4;
T8b949e// fetch lxmf messages from "us to destination" and from "destination to us"
Tff7b72const Te6edf3pageSize Tff7b72= T79c0ff30Tb4b4b4;
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/conversation/Tffd700${Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTffd700}Ta5d6ff`Tb4b4b4,
Tb4b4b4{
Te6edf3paramsTff7b72: Tb4b4b4{
Te6edf3countTff7b72: Te6edf3pageSizeTb4b4b4,
Te6edf3orderTff7b72: Ta5d6ff"desc"Tb4b4b4,
Te6edf3after_idTff7b72: Tff7b72thisTb4b4b4.Te6edf3oldestMessageIdTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}
Tb4b4b4)Tb4b4b4;
T8b949e// do nothing if response is for a previous request
Tff7b72if Tb4b4b4(Te6edf3seq Tff7b72!== Tff7b72thisTb4b4b4.Te6edf3lxmfMessagesRequestSequenceTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Ta5d6ff"ignoring response for previous lxmf messages request"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// convert lxmf messages to chat items
Tff7b72const Te6edf3chatItems Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3lxmfMessages Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3lxmf_messagesTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3lxmfMessage Tff7b72of Te6edf3lxmfMessagesTb4b4b4) Tb4b4b4{
Te6edf3chatItemsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"lxmf_message"Tb4b4b4,
Te6edf3is_outboundTff7b72: Tff7b72thisTb4b4b4.Te6edf3myLxmfAddressHash Tff7b72=== Te6edf3lxmfMessageTb4b4b4.Te6edf3source_hashTb4b4b4,
Te6edf3lxmf_messageTff7b72: Te6edf3lxmfMessageTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// add messages to start of existing messages
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3chatItem Tff7b72of Te6edf3chatItemsTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3unshiftTb4b4b4(Te6edf3chatItemTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// no more previous to load if received items is less than expected page size
Tff7b72if Tb4b4b4(Te6edf3chatItemsTb4b4b4.Te6edf3length Tff7b72< Te6edf3pageSizeTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3hasMorePrevious Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4{
T8b949e// do nothing
Tb4b4b4} Tff7b72finally Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3isLoadingPrevious Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3onWebsocketMessageTb4b4b4(Te6edf3messageTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3json Tff7b72= Tffa657JSONTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3messageTb4b4b4.Te6edf3dataTb4b4b4)Tb4b4b4;
Tff7b72switch Tb4b4b4(Te6edf3jsonTb4b4b4.Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72case Ta5d6ff"announce"Tff7b72: Tb4b4b4{
T8b949e// update stamp info and signal metrics if an announce is received from the selected peer
Tff7b72if Tb4b4b4(Te6edf3jsonTb4b4b4.Te6edf3announceTb4b4b4.Te6edf3destination_hash Tff7b72=== Tff7b72thisTb4b4b4.Te6edf3selectedPeerTff7b72?Tb4b4b4.Te6edf3destination_hashTb4b4b4) Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getPeerPathTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getPeerLxmfStampInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getPeerSignalMetricsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72case Ta5d6ff"lxmf.delivery"Tff7b72: Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onLxmfMessageReceivedTb4b4b4(Te6edf3jsonTb4b4b4.Te6edf3lxmf_messageTb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getPeerPathTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getPeerSignalMetricsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72case Ta5d6ff"lxmf_message_created"Tff7b72: Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onLxmfMessageCreatedTb4b4b4(Te6edf3jsonTb4b4b4.Te6edf3lxmf_messageTb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getPeerPathTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72case Ta5d6ff"lxmf_message_state_updated"Tff7b72: Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onLxmfMessageUpdatedTb4b4b4(Te6edf3jsonTb4b4b4.Te6edf3lxmf_messageTb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72case Ta5d6ff"lxmf_message_deleted"Tff7b72: Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onLxmfMessageDeletedTb4b4b4(Te6edf3jsonTb4b4b4.Te6edf3hashTb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3openLXMFAddressTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3GlobalEmitterTb4b4b4.Te6edf3emitTb4b4b4(Ta5d6ff"compose-new-message"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onComposeNewMessageEventTb4b4b4(Te6edf3destinationHashTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3selectedPeer Tff7b72&& Tff7b72!Te6edf3destinationHashTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3$nextTickTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3composeInput Tff7b72= Tffa657documentTb4b4b4.Te6edf3getElementByIdTb4b4b4(Ta5d6ff"compose-input"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3composeInputTb4b4b4) Tb4b4b4{
Te6edf3composeInputTb4b4b4.Te6edf3focusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3onComposeSubmitTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3composeAddress Tff7b72|| Tff7b72thisTb4b4b4.Te6edf3composeAddressTb4b4b4.Te6edf3trimTb4b4b4(Tb4b4b4) Tff7b72=== Ta5d6ff""Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72let Te6edf3destinationHash Tff7b72= Tff7b72thisTb4b4b4.Te6edf3composeAddressTb4b4b4.Te6edf3trimTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3composeAddress Tff7b72= Ta5d6ff""Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3handleComposeAddressTb4b4b4(Te6edf3destinationHashTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onComposeEnterPressedTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onComposeSubmitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3handleComposeAddressTb4b4b4(Te6edf3destinationHashTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3destinationHashTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"lxmf@"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3destinationHash Tff7b72= Te6edf3destinationHashTb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff"lxmf@"Tb4b4b4, Ta5d6ff""Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3destinationHashTb4b4b4.Te6edf3length Tff7b72!== T79c0ff32Tb4b4b4) Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff"Invalid Address"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3GlobalEmitterTb4b4b4.Te6edf3emitTb4b4b4(Ta5d6ff"compose-new-message"Tb4b4b4, Te6edf3destinationHashTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onLxmfMessageReceivedTb4b4b4(Te6edf3lxmfMessageTb4b4b4) Tb4b4b4{
T8b949e// only add if it's for the current conversation
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3source_hash Tff7b72!== Tff7b72thisTb4b4b4.Te6edf3selectedPeerTff7b72?Tb4b4b4.Te6edf3destination_hashTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// add inbound message to ui
Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"lxmf_message"Tb4b4b4,
Te6edf3lxmf_messageTff7b72: Te6edf3lxmfMessageTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// mark conversation as read
Tff7b72const Te6edf3conversation Tff7b72= Tff7b72thisTb4b4b4.Te6edf3findConversationTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3conversationTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3markConversationAsReadTb4b4b4(Te6edf3conversationTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// show notification for new messages if window is not focussed
Tff7b72if Tb4b4b4(Tff7b72!Tffa657documentTb4b4b4.Te6edf3hasFocusTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3NotificationUtilsTb4b4b4.Te6edf3showNewMessageNotificationTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// auto scroll to bottom if we want to
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3autoScrollOnNewMessageTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3scrollMessagesToBottomTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3onLxmfMessageCreatedTb4b4b4(Te6edf3lxmfMessageTb4b4b4) Tb4b4b4{
T8b949e// only add if it's for the current conversation
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3destination_hash Tff7b72!== Tff7b72thisTb4b4b4.Te6edf3selectedPeerTff7b72?Tb4b4b4.Te6edf3destination_hashTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// add new outbound lxmf message from server
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3isLxmfMessageInUiTb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3hashTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"lxmf_message"Tb4b4b4,
Te6edf3lxmf_messageTff7b72: Te6edf3lxmfMessageTb4b4b4,
Te6edf3is_outboundTff7b72: Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3onLxmfMessageUpdatedTb4b4b4(Te6edf3lxmfMessageTb4b4b4) Tb4b4b4{
T8b949e// find existing chat item by lxmf message hash
Tff7b72const Te6edf3lxmfMessageHash Tff7b72= Te6edf3lxmfMessageTb4b4b4.Te6edf3hashTb4b4b4;
Tff7b72const Te6edf3chatItemIndex Tff7b72= Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3findIndexTb4b4b4(
Tb4b4b4(Te6edf3chatItemTb4b4b4) Tb4b4b4=> Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTff7b72?Tb4b4b4.Te6edf3hash Tff7b72=== Te6edf3lxmfMessageHash
Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3chatItemIndex Tff7b72=== Tff7b72-T79c0ff1Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// update lxmf message from server, while ensuring ui updates from nested object change
Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4[Te6edf3chatItemIndexTb4b4b4]Tb4b4b4.Te6edf3lxmf_message Tff7b72= Te6edf3lxmfMessageTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onLxmfMessageDeletedTb4b4b4(Te6edf3hashTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3hashTb4b4b4) Tb4b4b4{
T8b949e// remove existing chat item by lxmf message hash
Tff7b72thisTb4b4b4.Te6edf3chatItems Tff7b72= Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3filterTb4b4b4(Tb4b4b4(Te6edf3itemTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3itemTb4b4b4.Te6edf3lxmf_messageTff7b72?Tb4b4b4.Te6edf3hash Tff7b72!== Te6edf3hashTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3getPeerPathTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// get path to destination
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/destination/Tffd700${Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTffd700}Ta5d6ff/pathTa5d6ff`
Tb4b4b4)Tb4b4b4;
T8b949e// update ui
Tff7b72thisTb4b4b4.Te6edf3selectedPeerPath Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3pathTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
T8b949e// clear previous known path
Tff7b72thisTb4b4b4.Te6edf3selectedPeerPath Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3getPeerLxmfStampInfoTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// get lxmf stamp info
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/destination/Tffd700${Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTffd700}Ta5d6ff/lxmf-stamp-infoTa5d6ff`
Tb4b4b4)Tb4b4b4;
T8b949e// update ui
Tff7b72thisTb4b4b4.Te6edf3selectedPeerLxmfStampInfo Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3lxmf_stamp_infoTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
T8b949e// clear previous stamp info
Tff7b72thisTb4b4b4.Te6edf3selectedPeerLxmfStampInfo Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3getPeerSignalMetricsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// get signal metrics
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/destination/Tffd700${Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTffd700}Ta5d6ff/signal-metricsTa5d6ff`
Tb4b4b4)Tb4b4b4;
T8b949e// update ui
Tff7b72thisTb4b4b4.Te6edf3selectedPeerSignalMetrics Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3signal_metricsTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
T8b949e// clear previous signal metrics
Tff7b72thisTb4b4b4.Te6edf3selectedPeerSignalMetrics Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3onDestinationPathClickTb4b4b4(Te6edf3pathTb4b4b4) Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff`Tffd700${Te6edf3pathTb4b4b4.Te6edf3hopsTffd700}Ta5d6ff Tffd700${Te6edf3pathTb4b4b4.Te6edf3hops Tff7b72=== T79c0ff1 Tff7b72? Ta5d6ff"hop" Tff7b72: Ta5d6ff"hops"Tffd700}Ta5d6ff away via Tffd700${Te6edf3pathTb4b4b4.Te6edf3next_hop_interfaceTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onStampInfoClickTb4b4b4(Te6edf3stampInfoTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3stampCost Tff7b72= Te6edf3stampInfoTb4b4b4.Te6edf3stamp_costTb4b4b4;
Tff7b72const Te6edf3outboundTicketExpiry Tff7b72= Te6edf3stampInfoTb4b4b4.Te6edf3outbound_ticket_expiryTb4b4b4;
T8b949e// determine estimated time to generate a stamp
Tff7b72var Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff""Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff24Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"several hours"Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff20Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"more than an hour"Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff18Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"~5 minutes"Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff17Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"a few minutes"Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff16Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"~1 minute"Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff13Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"~30 seconds"Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff9Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"~10 seconds"Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3stampCost Tff7b72>= T79c0ff1Tb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"a few seconds"Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff"0 seconds"Tb4b4b4;
Tb4b4b4}
T8b949e// check if we have an outbound ticket available
Tff7b72if Tb4b4b4(Te6edf3outboundTicketExpiry Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3estimatedTimeForStamp Tff7b72= Ta5d6ff`Ta5d6ffinstant (ticket expires Tffd700${Te6edf3dayjsTb4b4b4(Te6edf3outboundTicketExpiry Tff7b72* T79c0ff1000Tb4b4b4)Tb4b4b4.Te6edf3fromNowTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff`Tb4b4b4;
Tb4b4b4}
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(
Ta5d6ff`Ta5d6ffThis peer has enabled stamp security.Ta5d6ff\nTa5d6ff\nTa5d6ffYour device must have a ticket, or solve an automated proof of work task each time you send them a message.Ta5d6ff\nTa5d6ff\nTa5d6ffTime per message: Tffd700${Te6edf3estimatedTimeForStampTffd700}Ta5d6ff`
Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onSignalMetricsClickTb4b4b4(Te6edf3signalMetricsTb4b4b4) Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(
Tb4b4b4[
Ta5d6ff`Ta5d6ffSignal Quality: Tffd700${Te6edf3signalMetricsTb4b4b4.Te6edf3quality Tff7b72?? Ta5d6ff"???"Tffd700}Ta5d6ff%Ta5d6ff`Tb4b4b4,
Ta5d6ff`Ta5d6ffRSSI: Tffd700${Te6edf3signalMetricsTb4b4b4.Te6edf3rssi Tff7b72?? Ta5d6ff"???"Tffd700}Ta5d6ffdBmTa5d6ff`Tb4b4b4,
Ta5d6ff`Ta5d6ffSNR: Tffd700${Te6edf3signalMetricsTb4b4b4.Te6edf3snr Tff7b72?? Ta5d6ff"???"Tffd700}Ta5d6ffdBTa5d6ff`Tb4b4b4,
Tb4b4b4]Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff"\n"Tb4b4b4)
Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3scrollMessagesToBottomTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// next tick waits for the ui to have the new elements added
Tff7b72thisTb4b4b4.Te6edf3$nextTickTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// set timeout with zero millis seems to fix issue where it doesn't scroll all the way to the bottom...
Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3container Tff7b72= Tffa657documentTb4b4b4.Te6edf3getElementByIdTb4b4b4(Ta5d6ff"messages"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3containerTb4b4b4) Tb4b4b4{
Te6edf3containerTb4b4b4.Te6edf3scrollTop Tff7b72= Te6edf3containerTb4b4b4.Te6edf3scrollHeightTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3isLxmfMessageInUiTff7b72: Tff7b72function Tb4b4b4(Te6edf3hashTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3findIndexTb4b4b4(Tb4b4b4(Te6edf3chatItemTb4b4b4) Tb4b4b4=> Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTff7b72?Tb4b4b4.Te6edf3hash Tff7b72=== Te6edf3hashTb4b4b4) Tff7b72!== Tff7b72-T79c0ff1Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3getCustomDisplayNameTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// get custom display name
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/destination/Tffd700${Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTffd700}Ta5d6ff/custom-display-nameTa5d6ff`
Tb4b4b4)Tb4b4b4;
T8b949e// update ui
Tff7b72thisTb4b4b4.Te6edf3$emitTb4b4b4(Ta5d6ff"update:selectedPeer"Tb4b4b4, Tb4b4b4{
Tb4b4b4...Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4,
Te6edf3custom_display_nameTff7b72: Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3custom_display_nameTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3errorTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3errorTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3updateCustomDisplayNameTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// do nothing if no peer selected
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// ask user for new display name
Tff7b72const Te6edf3displayName Tff7b72= Tff7b72await Te6edf3DialogUtilsTb4b4b4.Te6edf3promptTb4b4b4(Ta5d6ff"Enter a custom display name"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3displayName Tff7b72== Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72try Tb4b4b4{
T8b949e// update display name on server
Tff7b72await Te6edf3axiosTb4b4b4.Te6edf3postTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/destination/Tffd700${Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTffd700}Ta5d6ff/custom-display-name/updateTa5d6ff`Tb4b4b4,
Tb4b4b4{
Te6edf3display_nameTff7b72: Te6edf3displayNameTb4b4b4,
Tb4b4b4}
Tb4b4b4)Tb4b4b4;
T8b949e// update display name in ui
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getCustomDisplayNameTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// reload conversations (so conversations list updates name)
Tff7b72thisTb4b4b4.Te6edf3$emitTb4b4b4(Ta5d6ff"reload-conversations"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3errorTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3errorTb4b4b4)Tb4b4b4;
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff"Failed to update display name"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3onConversationDeletedTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// reload conversation
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3initialLoadTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// reload conversations
Tff7b72thisTb4b4b4.Te6edf3$emitTb4b4b4(Ta5d6ff"reload-conversations"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onChatItemClickTff7b72: Tff7b72function Tb4b4b4(Te6edf3chatItemTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3chatItemTb4b4b4.Te6edf3is_actions_expandedTb4b4b4) Tb4b4b4{
Te6edf3chatItemTb4b4b4.Te6edf3is_actions_expanded Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3chatItemTb4b4b4.Te6edf3is_actions_expanded Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3downloadAndDecodeAudioTb4b4b4(Te6edf3chatItemTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3isDownloadingAudioTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4]Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3isDownloadingAudioTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4] Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72try Tb4b4b4{
T8b949e// fetch audio bytes from api
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(
Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/attachment/Tffd700${Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTffd700}Ta5d6ff/audioTa5d6ff`Tb4b4b4,
Tb4b4b4{
Te6edf3responseTypeTff7b72: Ta5d6ff"arraybuffer"Tb4b4b4,
Tb4b4b4}
Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3audioBytes Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4; T8b949e// this will be an ArrayBuffer
T8b949e// ensure we have the bytes
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3audioBytesTb4b4b4) Tb4b4b4{
Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff"No audio bytes received"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// decode audio to blob url
T8b949e// note: decodeLxmfAudioFieldToBlobUrl expects a field object with audio_mode and audio_bytes
Tff7b72const Te6edf3audioField Tff7b72= Tb4b4b4{
Te6edf3audio_modeTff7b72: Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4.Te6edf3audio_modeTb4b4b4,
Te6edf3audio_bytesTff7b72: Te6edf3audioBytesTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3objectUrl Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3decodeLxmfAudioFieldToBlobUrlTb4b4b4(Te6edf3audioFieldTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3objectUrlTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3lxmfMessageAudioAttachmentCacheTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4] Tff7b72= Te6edf3objectUrlTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff"Failed to download or decode audio:"Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff"Failed to load audio attachment."Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72finally Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3isDownloadingAudioTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4] Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3formatAttachmentSizeTb4b4b4(Te6edf3attachmentTb4b4b4, Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3attachmentTb4b4b4[Ta5d6ff`Tffd700${Te6edf3typeTffd700}Ta5d6ff_sizeTa5d6ff`Tb4b4b4] Tff7b72!== Tff7b72undefined Tff7b72&& Te6edf3attachmentTb4b4b4[Ta5d6ff`Tffd700${Te6edf3typeTffd700}Ta5d6ff_sizeTa5d6ff`Tb4b4b4] Tff7b72!== Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3formatBytesTb4b4b4(Te6edf3attachmentTb4b4b4[Ta5d6ff`Tffd700${Te6edf3typeTffd700}Ta5d6ff_sizeTa5d6ff`Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3attachmentTb4b4b4[Ta5d6ff`Tffd700${Te6edf3typeTffd700}Ta5d6ff_bytesTa5d6ff`Tb4b4b4]Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3formatBase64BytesTb4b4b4(Te6edf3attachmentTb4b4b4[Ta5d6ff`Tffd700${Te6edf3typeTffd700}Ta5d6ff_bytesTa5d6ff`Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Ta5d6ff"0 B"Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3openImageTff7b72: Tff7b72async Tff7b72function Tb4b4b4(Te6edf3urlTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3imageModalUrl Tff7b72= Te6edf3urlTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3closeImageModalTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3imageModalUrl Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3downloadFileFromBase64Tff7b72: Tff7b72async Tff7b72function Tb4b4b4(Te6edf3fileNameTb4b4b4, Te6edf3fileBytesBase64Tb4b4b4) Tb4b4b4{
T8b949e// create blob from base64 encoded file bytes
Tff7b72const Te6edf3byteCharacters Tff7b72= Te6edf3atobTb4b4b4(Te6edf3fileBytesBase64Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3byteNumbers Tff7b72= Tff7b72new Tffa657ArrayTb4b4b4(Te6edf3byteCharactersTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3byteCharactersTb4b4b4.Te6edf3lengthTb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Te6edf3byteNumbersTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3byteCharactersTb4b4b4.Te6edf3charCodeAtTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3byteArray Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3byteNumbersTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3blob Tff7b72= Tff7b72new Te6edf3BlobTb4b4b4(Tb4b4b4[Te6edf3byteArrayTb4b4b4]Tb4b4b4)Tb4b4b4;
T8b949e// create object url for blob
Tff7b72const Te6edf3objectUrl Tff7b72= Te6edf3URLTb4b4b4.Te6edf3createObjectURLTb4b4b4(Te6edf3blobTb4b4b4)Tb4b4b4;
T8b949e// create link element to download blob
Tff7b72const Te6edf3link Tff7b72= Tffa657documentTb4b4b4.Te6edf3createElementTb4b4b4(Ta5d6ff"a"Tb4b4b4)Tb4b4b4;
Te6edf3linkTb4b4b4.Te6edf3href Tff7b72= Te6edf3objectUrlTb4b4b4;
Te6edf3linkTb4b4b4.Te6edf3download Tff7b72= Te6edf3fileNameTb4b4b4;
Te6edf3linkTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Ta5d6ff"none"Tb4b4b4;
Tffa657documentTb4b4b4.Te6edf3bodyTb4b4b4.Te6edf3appendTb4b4b4(Te6edf3linkTb4b4b4)Tb4b4b4;
T8b949e// click link to download file in browser
Te6edf3linkTb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// link element is no longer needed
Te6edf3linkTb4b4b4.Te6edf3removeTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// revoke object url to clear memory
Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3URLTb4b4b4.Te6edf3revokeObjectURLTb4b4b4(Te6edf3objectUrlTb4b4b4)Tb4b4b4, T79c0ff10000Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3processAudioForSelectedPeerChatItemsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3chatItem Tff7b72of Tff7b72thisTb4b4b4.Te6edf3selectedPeerChatItemsTb4b4b4) Tb4b4b4{
T8b949e// skip if no audio, or if audio bytes are missing (must be downloaded manually)
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTff7b72?Tb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3audio Tff7b72|| Tff7b72!Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4.Te6edf3audio_bytesTb4b4b4) Tb4b4b4{
Tff7b72continueTb4b4b4;
Tb4b4b4}
T8b949e// skip if audio already cached
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3lxmfMessageAudioAttachmentCacheTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4]Tb4b4b4) Tb4b4b4{
Tff7b72continueTb4b4b4;
Tb4b4b4}
T8b949e// decode audio to blob url
Tff7b72const Te6edf3objectUrl Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3decodeLxmfAudioFieldToBlobUrlTb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3objectUrlTb4b4b4) Tb4b4b4{
Tff7b72continueTb4b4b4;
Tb4b4b4}
T8b949e// update audio cache
Tff7b72thisTb4b4b4.Te6edf3lxmfMessageAudioAttachmentCacheTb4b4b4[Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4] Tff7b72= Te6edf3objectUrlTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3decodeLxmfAudioFieldToBlobUrlTb4b4b4(Te6edf3audioFieldTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// get audio mode and audio bytes from audio field
Tff7b72const Te6edf3audioMode Tff7b72= Te6edf3audioFieldTb4b4b4.Te6edf3audio_modeTb4b4b4;
Tff7b72const Te6edf3audioBytes Tff7b72= Te6edf3audioFieldTb4b4b4.Te6edf3audio_bytesTb4b4b4;
T8b949e// handle opus: AM_OPUS_OGG
Tff7b72if Tb4b4b4(Te6edf3audioMode Tff7b72=== T79c0ff0x10Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3decodeOpusAudioToBlobUrlTb4b4b4(Te6edf3audioFieldTb4b4b4.Te6edf3audio_bytesTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// determine codec2 mode, or skip if unknown
Tff7b72const Te6edf3codecMode Tff7b72= Tff7b72thisTb4b4b4.Te6edf3lxmfAudioModeToCodec2ModeMapTb4b4b4[Te6edf3audioModeTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3codecModeTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Ta5d6ff"unsupported audio mode: " Tff7b72+ Te6edf3audioModeTb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
T8b949e// convert to uint8 array
Tff7b72let Te6edf3encodedTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72typeof Te6edf3audioBytes Tff7b72=== Ta5d6ff"string"Tb4b4b4) Tb4b4b4{
Te6edf3encoded Tff7b72= Tff7b72thisTb4b4b4.Te6edf3base64ToArrayBufferTb4b4b4(Te6edf3audioBytesTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3encoded Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3audioBytesTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// decode codec2 audio
Tff7b72const Te6edf3decoded Tff7b72= Tff7b72await Te6edf3Codec2LibTb4b4b4.Te6edf3runDecodeTb4b4b4(Te6edf3codecModeTb4b4b4, Te6edf3encodedTb4b4b4)Tb4b4b4;
T8b949e// convert decoded codec2 to wav audio
Tff7b72const Te6edf3wavAudio Tff7b72= Tff7b72await Te6edf3Codec2LibTb4b4b4.Te6edf3rawToWavTb4b4b4(Te6edf3decodedTb4b4b4)Tb4b4b4;
T8b949e// create blob from wav audio
Tff7b72const Te6edf3blob Tff7b72= Tff7b72new Te6edf3BlobTb4b4b4(Tb4b4b4[Te6edf3wavAudioTb4b4b4]Tb4b4b4, Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"audio/wav"Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// create object url for blob
Tff7b72return Te6edf3URLTb4b4b4.Te6edf3createObjectURLTb4b4b4(Te6edf3blobTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// failed to decode lxmf audio field
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3decodeOpusAudioToBlobUrlTb4b4b4(Te6edf3audioBytesTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// convert to uint8 array
Tff7b72let Te6edf3opusAudioBytesTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72typeof Te6edf3audioBytes Tff7b72=== Ta5d6ff"string"Tb4b4b4) Tb4b4b4{
Te6edf3opusAudioBytes Tff7b72= Tff7b72thisTb4b4b4.Te6edf3base64ToArrayBufferTb4b4b4(Te6edf3audioBytesTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3opusAudioBytes Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3audioBytesTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// create blob from opus audio
Tff7b72const Te6edf3blob Tff7b72= Tff7b72new Te6edf3BlobTb4b4b4(Tb4b4b4[Te6edf3opusAudioBytesTb4b4b4]Tb4b4b4, Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"audio/opus"Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// create object url for blob
Tff7b72return Te6edf3URLTb4b4b4.Te6edf3createObjectURLTb4b4b4(Te6edf3blobTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// failed to decode opus audio
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3base64ToArrayBufferTff7b72: Tff7b72function Tb4b4b4(Te6edf3base64Tb4b4b4) Tb4b4b4{
Tff7b72return Tffa657Uint8ArrayTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3atobTb4b4b4(Te6edf3base64Tb4b4b4)Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4) Tb4b4b4=> Te6edf3cTb4b4b4.Te6edf3charCodeAtTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3deleteChatItemTb4b4b4(Te6edf3chatItemTb4b4b4, Te6edf3shouldConfirm Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// ask user to confirm deleting message
Tff7b72if Tb4b4b4(
Te6edf3shouldConfirm Tff7b72&&
Tff7b72!Tb4b4b4(Tff7b72await Te6edf3DialogUtilsTb4b4b4.Te6edf3confirmTb4b4b4(
Ta5d6ff"Are you sure you want to delete this message? This can not be undone!"
Tb4b4b4)Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// make sure it's an lxmf message
Tff7b72if Tb4b4b4(Te6edf3chatItemTb4b4b4.Te6edf3type Tff7b72!== Ta5d6ff"lxmf_message"Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// delete lxmf message from server
Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Tff7b72deleteTb4b4b4(Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/Tffd700${Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
T8b949e// remove lxmf message from chat items using hash, as other pending items might not have an id yet
Tff7b72thisTb4b4b4.Te6edf3chatItems Tff7b72= Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3filterTb4b4b4(Tb4b4b4(Te6edf3itemTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3itemTb4b4b4.Te6edf3lxmf_messageTff7b72?Tb4b4b4.Te6edf3hash Tff7b72!== Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4{
T8b949e// do nothing if failed to delete message
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3openShareContactModalTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(Ta5d6ff"/api/v1/telephone/contacts"Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3contacts Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3contactsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3ToastUtilsTb4b4b4.Te6edf3infoTb4b4b4(Ta5d6ff"No contacts found in telephone"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3isShareContactModalOpen Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3ToastUtilsTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff"Failed to load contacts"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3shareContactTb4b4b4(Te6edf3contactTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3newMessageText Tff7b72= Ta5d6ff`Ta5d6ffContact: Tffd700${Te6edf3contactTb4b4b4.Te6edf3nameTffd700}Ta5d6ff <Tffd700${Te6edf3contactTb4b4b4.Te6edf3remote_identity_hashTffd700}Ta5d6ff>Ta5d6ff`Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3isShareContactModalOpen Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3sendMessageTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3sendMessageTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// do nothing if can't send message
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3canSendMessageTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// do nothing if no peer selected
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3isSendingMessage Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72try Tb4b4b4{
T8b949e// build fields
Tff7b72const Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
T8b949e// add telemetry if present
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3newMessageTelemetryTb4b4b4) Tb4b4b4{
Te6edf3fieldsTb4b4b4[Ta5d6ff"telemetry"Tb4b4b4] Tff7b72= Tff7b72thisTb4b4b4.Te6edf3newMessageTelemetryTb4b4b4;
Tb4b4b4}
T8b949e// add file attachments
Tff7b72var Te6edf3fileAttachmentsTotalSize Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3newMessageFilesTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3fileAttachments Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3file Tff7b72of Tff7b72thisTb4b4b4.Te6edf3newMessageFilesTb4b4b4) Tb4b4b4{
Te6edf3fileAttachmentsTotalSize Tff7b72+= Te6edf3fileTb4b4b4.Te6edf3sizeTb4b4b4;
Te6edf3fileAttachmentsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3file_nameTff7b72: Te6edf3fileTb4b4b4.Te6edf3nameTb4b4b4,
Te6edf3file_bytesTff7b72: Te6edf3UtilsTb4b4b4.Te6edf3arrayBufferToBase64Tb4b4b4(Tff7b72await Te6edf3fileTb4b4b4.Te6edf3arrayBufferTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3fieldsTb4b4b4[Ta5d6ff"file_attachments"Tb4b4b4] Tff7b72= Te6edf3fileAttachmentsTb4b4b4;
Tb4b4b4}
T8b949e// add image attachment
Tff7b72var Te6edf3imageTotalSize Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3newMessageImageTb4b4b4) Tb4b4b4{
Te6edf3imageTotalSize Tff7b72= Tff7b72thisTb4b4b4.Te6edf3newMessageImageTb4b4b4.Te6edf3sizeTb4b4b4;
Te6edf3fieldsTb4b4b4[Ta5d6ff"image"Tb4b4b4] Tff7b72= Tb4b4b4{
T8b949e// Reticulum sends image type as "jpg", "png", "webp" etc and not "image/jpg" or "image/png"
T8b949e// From memory, Sideband would not display images if the image type has the "image/" prefix
T8b949e// https://github.com/markqvist/Sideband/blob/354fb08297835eab04ac69d15081a18baf0583ac/docs/example_plugins/view.py#L78
T8b949e// https://github.com/markqvist/Sideband/blob/354fb08297835eab04ac69d15081a18baf0583ac/sbapp/main.py#L1900
T8b949e// https://github.com/markqvist/Sideband/blob/354fb08297835eab04ac69d15081a18baf0583ac/sbapp/ui/messages.py#L783
Te6edf3image_typeTff7b72: Tff7b72thisTb4b4b4.Te6edf3newMessageImageTb4b4b4.Te6edf3typeTb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff"image/"Tb4b4b4, Ta5d6ff""Tb4b4b4)Tb4b4b4,
Te6edf3image_bytesTff7b72: Te6edf3UtilsTb4b4b4.Te6edf3arrayBufferToBase64Tb4b4b4(Tff7b72await Tff7b72thisTb4b4b4.Te6edf3newMessageImageTb4b4b4.Te6edf3arrayBufferTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e// add audio attachment
Tff7b72var Te6edf3audioTotalSize Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3newMessageAudioTb4b4b4) Tb4b4b4{
Te6edf3audioTotalSize Tff7b72= Tff7b72thisTb4b4b4.Te6edf3newMessageAudioTb4b4b4.Te6edf3sizeTb4b4b4;
Te6edf3fieldsTb4b4b4[Ta5d6ff"audio"Tb4b4b4] Tff7b72= Tb4b4b4{
Te6edf3audio_modeTff7b72: Tff7b72thisTb4b4b4.Te6edf3newMessageAudioTb4b4b4.Te6edf3audio_modeTb4b4b4,
Te6edf3audio_bytesTff7b72: Te6edf3UtilsTb4b4b4.Te6edf3arrayBufferToBase64Tb4b4b4(Tff7b72await Tff7b72thisTb4b4b4.Te6edf3newMessageAudioTb4b4b4.Te6edf3audio_blobTb4b4b4.Te6edf3arrayBufferTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e// calculate estimated message size in bytes
Tff7b72const Te6edf3contentSize Tff7b72= Tff7b72thisTb4b4b4.Te6edf3newMessageTextTb4b4b4.Te6edf3lengthTb4b4b4;
Tff7b72const Te6edf3totalMessageSize Tff7b72= Te6edf3contentSize Tff7b72+ Te6edf3fileAttachmentsTotalSize Tff7b72+ Te6edf3imageTotalSize Tff7b72+ Te6edf3audioTotalSizeTb4b4b4;
T8b949e// ask user if they still want to send message if it may be rejected by sender
Tff7b72if Tb4b4b4(Te6edf3totalMessageSize Tff7b72> T79c0ff1000 Tff7b72* T79c0ff900Tb4b4b4) Tb4b4b4{
T8b949e// actual limit in LXMF Router is 1mb
Tff7b72if Tb4b4b4(
Tff7b72!Tb4b4b4(Tff7b72await Te6edf3DialogUtilsTb4b4b4.Te6edf3confirmTb4b4b4(
Ta5d6ff`Ta5d6ffYour message exceeds 900KB (It's Tffd700${Tff7b72thisTb4b4b4.Te6edf3formatBytesTb4b4b4(Te6edf3totalMessageSizeTb4b4b4)Tffd700}Ta5d6ff). It may be rejected by the recipient unless they have increased their delivery limit. Do you want to try sending anyway?Ta5d6ff`
Tb4b4b4)Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// send message to reticulum
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3postTb4b4b4(Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/sendTa5d6ff`Tb4b4b4, Tb4b4b4{
Te6edf3delivery_methodTff7b72: Tff7b72thisTb4b4b4.Te6edf3newMessageDeliveryMethodTb4b4b4,
Te6edf3lxmf_messageTff7b72: Tb4b4b4{
Te6edf3destination_hashTff7b72: Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTb4b4b4,
Te6edf3contentTff7b72: Tff7b72thisTb4b4b4.Te6edf3newMessageTextTb4b4b4,
Te6edf3fieldsTff7b72: Te6edf3fieldsTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// add outbound message to ui
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3isLxmfMessageInUiTb4b4b4(Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"lxmf_message"Tb4b4b4,
Te6edf3lxmf_messageTff7b72: Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3lxmf_messageTb4b4b4,
Te6edf3is_outboundTff7b72: Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// always scroll to bottom since we just sent a message
Tff7b72thisTb4b4b4.Te6edf3scrollMessagesToBottomTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// clear message inputs
Tff7b72thisTb4b4b4.Te6edf3newMessageText Tff7b72= Ta5d6ff""Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3newMessageImage Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3newMessageImageUrl Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3newMessageAudio Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3newMessageTelemetry Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3newMessageFiles Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3clearFileInputTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// show error
Tff7b72const Te6edf3message Tff7b72= Te6edf3eTb4b4b4.Te6edf3responseTff7b72?Tb4b4b4.Te6edf3dataTff7b72?Tb4b4b4.Te6edf3message Tff7b72?? Ta5d6ff"failed to send message"Tb4b4b4;
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72finally Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3isSendingMessage Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3cancelSendingMessageTb4b4b4(Te6edf3chatItemTb4b4b4) Tb4b4b4{
T8b949e// get lxmf message hash else do nothing
Tff7b72const Te6edf3lxmfMessageHash Tff7b72= Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3lxmfMessageHashTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72try Tb4b4b4{
T8b949e// cancel sending lxmf message
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3postTb4b4b4(Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/Tffd700${Te6edf3lxmfMessageHashTffd700}Ta5d6ff/cancelTa5d6ff`Tb4b4b4)Tb4b4b4;
T8b949e// get lxmf message from response
Tff7b72const Te6edf3lxmfMessage Tff7b72= Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3lxmf_messageTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3lxmfMessageTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// update lxmf message in ui
Tff7b72thisTb4b4b4.Te6edf3onLxmfMessageUpdatedTb4b4b4(Te6edf3lxmfMessageTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// show error
Tff7b72const Te6edf3message Tff7b72= Te6edf3eTb4b4b4.Te6edf3responseTff7b72?Tb4b4b4.Te6edf3dataTff7b72?Tb4b4b4.Te6edf3message Tff7b72?? Ta5d6ff"failed to cancel message"Tb4b4b4;
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3retrySendingMessageTb4b4b4(Te6edf3chatItemTb4b4b4) Tb4b4b4{
T8b949e// force delete existing message
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3deleteChatItemTb4b4b4(Te6edf3chatItemTb4b4b4, Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
T8b949e// send message to reticulum
Tff7b72const Te6edf3response Tff7b72= Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3postTb4b4b4(Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/sendTa5d6ff`Tb4b4b4, Tb4b4b4{
Te6edf3lxmf_messageTff7b72: Tb4b4b4{
Te6edf3destination_hashTff7b72: Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3destination_hashTb4b4b4,
Te6edf3contentTff7b72: Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3contentTb4b4b4,
Te6edf3fieldsTff7b72: Te6edf3chatItemTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3fieldsTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// add outbound message to ui
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3isLxmfMessageInUiTb4b4b4(Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3lxmf_messageTb4b4b4.Te6edf3hashTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3chatItemsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"lxmf_message"Tb4b4b4,
Te6edf3lxmf_messageTff7b72: Te6edf3responseTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3lxmf_messageTb4b4b4,
Te6edf3is_outboundTff7b72: Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// always scroll to bottom since we just sent a message
Tff7b72thisTb4b4b4.Te6edf3scrollMessagesToBottomTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// show error
Tff7b72const Te6edf3message Tff7b72= Te6edf3eTb4b4b4.Te6edf3responseTff7b72?Tb4b4b4.Te6edf3dataTff7b72?Tb4b4b4.Te6edf3message Tff7b72?? Ta5d6ff"failed to send message"Tb4b4b4;
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3shareLocationTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3navigatorTb4b4b4.Te6edf3geolocationTb4b4b4) Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff"Geolocation is not supported by your browser"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3navigatorTb4b4b4.Te6edf3geolocationTb4b4b4.Te6edf3getCurrentPositionTb4b4b4(
Tb4b4b4(Te6edf3positionTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3newMessageTelemetry Tff7b72= Tb4b4b4{
Te6edf3latitudeTff7b72: Te6edf3positionTb4b4b4.Te6edf3coordsTb4b4b4.Te6edf3latitudeTb4b4b4,
Te6edf3longitudeTff7b72: Te6edf3positionTb4b4b4.Te6edf3coordsTb4b4b4.Te6edf3longitudeTb4b4b4,
Te6edf3altitudeTff7b72: Te6edf3positionTb4b4b4.Te6edf3coordsTb4b4b4.Te6edf3altitude Tff7b72|| T79c0ff0Tb4b4b4,
Te6edf3speedTff7b72: Tb4b4b4(Te6edf3positionTb4b4b4.Te6edf3coordsTb4b4b4.Te6edf3speed Tff7b72|| T79c0ff0Tb4b4b4) Tff7b72* T79c0ff3.6Tb4b4b4, T8b949e// m/s to km/h to match Sideband
Te6edf3bearingTff7b72: Te6edf3positionTb4b4b4.Te6edf3coordsTb4b4b4.Te6edf3heading Tff7b72|| T79c0ff0Tb4b4b4,
Te6edf3accuracyTff7b72: Te6edf3positionTb4b4b4.Te6edf3coordsTb4b4b4.Te6edf3accuracy Tff7b72|| T79c0ff0Tb4b4b4,
Te6edf3last_updateTff7b72: Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1000Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3sendMessageTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4(Te6edf3errorTb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff`Ta5d6ffFailed to get location: Tffd700${Te6edf3errorTb4b4b4.Te6edf3messageTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4{
Te6edf3enableHighAccuracyTff7b72: Tff7b72trueTb4b4b4,
Te6edf3timeoutTff7b72: T79c0ff30000Tb4b4b4,
Te6edf3maximumAgeTff7b72: T79c0ff0Tb4b4b4,
Tb4b4b4}
Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3requestLocationTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tff7b72returnTb4b4b4;
T8b949e// Send a telemetry request command
Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3postTb4b4b4(Ta5d6ff`Ta5d6ff/api/v1/lxmf-messages/sendTa5d6ff`Tb4b4b4, Tb4b4b4{
Te6edf3lxmf_messageTff7b72: Tb4b4b4{
Te6edf3destination_hashTff7b72: Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hashTb4b4b4,
Te6edf3contentTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3fieldsTff7b72: Tb4b4b4{
Te6edf3commandsTff7b72: Tb4b4b4[
Tb4b4b4{ Ta5d6ff"0x01"Tff7b72: Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1000Tb4b4b4) Tb4b4b4}Tb4b4b4, T8b949e// Sideband TELEMETRY_REQUEST
Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3ToastUtilsTb4b4b4.Te6edf3successTb4b4b4(Ta5d6ff"Location request sent"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3ToastUtilsTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff"Failed to send location request"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3viewLocationOnMapTb4b4b4(Te6edf3locationTb4b4b4) Tb4b4b4{
T8b949e// navigate to map and center on location
Tff7b72thisTb4b4b4.Te6edf3$routerTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3nameTff7b72: Ta5d6ff"map"Tb4b4b4,
Te6edf3queryTff7b72: Tb4b4b4{
Te6edf3latTff7b72: Te6edf3locationTb4b4b4.Te6edf3latitudeTb4b4b4,
Te6edf3lonTff7b72: Te6edf3locationTb4b4b4.Te6edf3longitudeTb4b4b4,
Te6edf3zoomTff7b72: T79c0ff15Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3formatTimeAgoTff7b72: Tff7b72function Tb4b4b4(Te6edf3datetimeStringTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3UtilsTb4b4b4.Te6edf3formatTimeAgoTb4b4b4(Te6edf3datetimeStringTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3formatBytesTff7b72: Tff7b72function Tb4b4b4(Te6edf3bytesTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3UtilsTb4b4b4.Te6edf3formatBytesTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3base64ByteLengthTb4b4b4(Te6edf3base64StringTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3base64StringTb4b4b4) Tb4b4b4{
Tff7b72return T79c0ff0Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3padding Tff7b72= Tb4b4b4(Te6edf3base64StringTb4b4b4.Te6edf3matchTb4b4b4(Ta5d6ff/=+$/Tb4b4b4) Tff7b72|| Tb4b4b4[Ta5d6ff""Tb4b4b4]Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3lengthTb4b4b4;
Tff7b72return Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tb4b4b4(Te6edf3base64StringTb4b4b4.Te6edf3length Tff7b72* T79c0ff3Tb4b4b4) Tff7b72/ T79c0ff4Tb4b4b4) Tff7b72- Te6edf3paddingTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3formatBase64BytesTb4b4b4(Te6edf3base64StringTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3formatBytesTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3base64ByteLengthTb4b4b4(Te6edf3base64StringTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3openConversationPopoutTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3destinationHash Tff7b72= Tff7b72thisTb4b4b4.Te6edf3selectedPeerTb4b4b4.Te6edf3destination_hash Tff7b72|| Ta5d6ff""Tb4b4b4;
Tff7b72const Te6edf3encodedHash Tff7b72= Tffa657encodeURIComponentTb4b4b4(Te6edf3destinationHashTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3url Tff7b72= Ta5d6ff`Tffd700${Tffa657windowTb4b4b4.Te6edf3locationTb4b4b4.Te6edf3originTffd700}Tffd700${Tffa657windowTb4b4b4.Te6edf3locationTb4b4b4.Te6edf3pathnameTffd700}Ta5d6ff#/popout/messages/Tffd700${Te6edf3encodedHashTffd700}Ta5d6ff`Tb4b4b4;
Tffa657windowTb4b4b4.Te6edf3openTb4b4b4(Te6edf3urlTb4b4b4, Ta5d6ff"_blank"Tb4b4b4, Ta5d6ff"width=960,height=720,noopener"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onFileInputChangeTff7b72: Tff7b72function Tb4b4b4(Te6edf3eventTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3file Tff7b72of Te6edf3eventTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3filesTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3newMessageFilesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3fileTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3clearFileInputTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3$refsTb4b4b4[Ta5d6ff"file-input"Tb4b4b4]Tb4b4b4.Te6edf3value Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3removeImageAttachmentTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// ask user to confirm removing image attachment
Tff7b72if Tb4b4b4(Tff7b72!Tb4b4b4(Tff7b72await Te6edf3DialogUtilsTb4b4b4.Te6edf3confirmTb4b4b4(Ta5d6ff"Are you sure you want to remove this image attachment?"Tb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// remove image
Tff7b72thisTb4b4b4.Te6edf3newMessageImage Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3newMessageImageUrl Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onImageSelectedTff7b72: Tff7b72function Tb4b4b4(Te6edf3imageBlobTb4b4b4) Tb4b4b4{
T8b949e// update selected file
Tff7b72thisTb4b4b4.Te6edf3newMessageImage Tff7b72= Te6edf3imageBlobTb4b4b4;
T8b949e// update image url when file is read
Tff7b72const Te6edf3fileReader Tff7b72= Tff7b72new Te6edf3FileReaderTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3fileReaderTb4b4b4.Te6edf3onload Tff7b72= Tb4b4b4(Te6edf3eventTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3newMessageImageUrl Tff7b72= Te6edf3eventTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3resultTb4b4b4;
Tb4b4b4}Tb4b4b4;
T8b949e// convert image to data url
Te6edf3fileReaderTb4b4b4.Te6edf3readAsDataURLTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3newMessageImageTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3startRecordingAudioAttachmentTb4b4b4(Te6edf3argsTb4b4b4) Tb4b4b4{
T8b949e// do nothing if already recording
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3isRecordingAudioAttachmentTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// ask user to confirm recording new audio attachment, if an existing audio attachment exists
Tff7b72if Tb4b4b4(
Tff7b72thisTb4b4b4.Te6edf3newMessageAudio Tff7b72&&
Tff7b72!Tb4b4b4(Tff7b72await Te6edf3DialogUtilsTb4b4b4.Te6edf3confirmTb4b4b4(
Ta5d6ff"An audio recording is already attached. A new recording will replace it. Do you want to continue?"
Tb4b4b4)Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// handle selected codec
Tff7b72switch Tb4b4b4(Te6edf3argsTb4b4b4.Te6edf3codecTb4b4b4) Tb4b4b4{
Tff7b72case Ta5d6ff"codec2"Tff7b72: Tb4b4b4{
T8b949e// start recording microphone
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderCodec Tff7b72= Ta5d6ff"codec2"Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorder Tff7b72= Tff7b72new Te6edf3Codec2MicrophoneRecorderTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderTb4b4b4.Te6edf3codec2Mode Tff7b72= Te6edf3argsTb4b4b4.Te6edf3modeTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingStartedAt Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3isRecordingAudioAttachment Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderTb4b4b4.Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// update recording time in ui every second
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingDuration Tff7b72= Te6edf3UtilsTb4b4b4.Te6edf3formatMinutesSecondsTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingTimer Tff7b72= Te6edf3setIntervalTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3recordingDurationMillis Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72- Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingStartedAtTb4b4b4;
Tff7b72const Te6edf3recordingDurationSeconds Tff7b72= Te6edf3recordingDurationMillis Tff7b72/ T79c0ff1000Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingDuration Tff7b72= Te6edf3UtilsTb4b4b4.Te6edf3formatMinutesSecondsTb4b4b4(Te6edf3recordingDurationSecondsTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, T79c0ff1000Tb4b4b4)Tb4b4b4;
T8b949e// alert if failed to start recording
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3isRecordingAudioAttachmentTb4b4b4) Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff"failed to start recording"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72case Ta5d6ff"opus"Tff7b72: Tb4b4b4{
T8b949e// start recording microphone
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderCodec Tff7b72= Ta5d6ff"opus"Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorder Tff7b72= Tff7b72new Te6edf3MicrophoneRecorderTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingStartedAt Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3isRecordingAudioAttachment Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderTb4b4b4.Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// update recording time in ui every second
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingDuration Tff7b72= Te6edf3UtilsTb4b4b4.Te6edf3formatMinutesSecondsTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingTimer Tff7b72= Te6edf3setIntervalTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3recordingDurationMillis Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72- Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingStartedAtTb4b4b4;
Tff7b72const Te6edf3recordingDurationSeconds Tff7b72= Te6edf3recordingDurationMillis Tff7b72/ T79c0ff1000Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingDuration Tff7b72= Te6edf3UtilsTb4b4b4.Te6edf3formatMinutesSecondsTb4b4b4(Te6edf3recordingDurationSecondsTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, T79c0ff1000Tb4b4b4)Tb4b4b4;
T8b949e// alert if failed to start recording
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3isRecordingAudioAttachmentTb4b4b4) Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff"failed to start recording"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72defaultTff7b72: Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff`Ta5d6ffUnhandled microphone recorder codec: Tffd700${Te6edf3argsTb4b4b4.Te6edf3codecTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3stopRecordingAudioAttachmentTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// clear audio recording timer
Te6edf3clearIntervalTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3audioAttachmentRecordingTimerTb4b4b4)Tb4b4b4;
T8b949e// do nothing if not recording
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3isRecordingAudioAttachmentTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// stop recording microphone and get audio
Tff7b72thisTb4b4b4.Te6edf3isRecordingAudioAttachment Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72const Te6edf3audio Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderTb4b4b4.Te6edf3stopTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// handle audio based on codec
Tff7b72switch Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderCodecTb4b4b4) Tb4b4b4{
Tff7b72case Ta5d6ff"codec2"Tff7b72: Tb4b4b4{
T8b949e// do nothing if no audio was provided
Tff7b72if Tb4b4b4(Te6edf3audioTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// decode codec2 audio back to wav so we can show a preview audio player before user sends it
Tff7b72const Te6edf3codec2Mode Tff7b72= Tff7b72thisTb4b4b4.Te6edf3audioAttachmentMicrophoneRecorderTb4b4b4.Te6edf3codec2ModeTb4b4b4;
Tff7b72const Te6edf3decoded Tff7b72= Tff7b72await Te6edf3Codec2LibTb4b4b4.Te6edf3runDecodeTb4b4b4(Te6edf3codec2ModeTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3audioTb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e// convert decoded codec2 to wav audio and create a blob
Tff7b72const Te6edf3wavAudio Tff7b72= Tff7b72await Te6edf3Codec2LibTb4b4b4.Te6edf3rawToWavTb4b4b4(Te6edf3decodedTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3wavBlob Tff7b72= Tff7b72new Te6edf3BlobTb4b4b4(Tb4b4b4[Te6edf3wavAudioTb4b4b4]Tb4b4b4, Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"audio/wav"Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// determine audio mode
Tff7b72var Te6edf3audioMode Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72switch Tb4b4b4(Te6edf3codec2ModeTb4b4b4) Tb4b4b4{
Tff7b72case Ta5d6ff"1200"Tff7b72: Tb4b4b4{
Te6edf3audioMode Tff7b72= T79c0ff0x04Tb4b4b4; T8b949e// LXMF.AM_CODEC2_1200
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72case Ta5d6ff"3200"Tff7b72: Tb4b4b4{
Te6edf3audioMode Tff7b72= T79c0ff0x09Tb4b4b4; T8b949e// LXMF.AM_CODEC2_3200
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72defaultTff7b72: Tb4b4b4{
Te6edf3DialogUtilsTb4b4b4.Te6edf3alertTb4b4b4(Ta5d6ff`Ta5d6ffUnhandled microphone recorder codec2Mode: Tffd700${Te6edf3codec2ModeTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// update message audio attachment
Tff7b72thisTb4b4b4.Te6edf3newMessageAudio Tff7b72= Tb4b4b4{
Te6edf3audio_modeTff7b72: Te6edf3audioModeTb4b4b4,
Te6edf3audio_blobTff7b72: Tff7b72new Te6edf3BlobTb4b4b4(Tb4b4b4[Te6edf3audioTb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3audio_preview_urlTff7b72: Te6edf3URLTb4b4b4.Te6edf3createObjectURLTb4b4b4(Te6edf3wavBlobTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tff7b72case Ta5d6ff"opus"Tff7b72: Tb4b4b4{
T8b949e// do nothing if no audio was provided
Tff7b72if Tb4b4b4(Te6edf3audioTb4b4b4.Te6edf3size Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// update message audio attachment
Tff7b72thisTb4b4b4.Te6edf3newMessageAudio Tff7b72= Tb4b4b4{
Te6edf3audio_modeTff7b72: T79c0ff0x10Tb4b4b4, T8b949e// LXMF.AM_OPUS_OGG
Te6edf3audio_blobTff7b72: Te6edf3audioTb4b4b4, T8b949e// opus microphone recorder returns a blob
Te6edf3audio_preview_urlTff7b72: Te6edf3URLTb4b4b4.Te6edf3createObjectURLTb4b4b4(Te6edf3audioTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3removeAudioAttachmentTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// ask user to confirm removing audio attachment
Tff7b72if Tb4b4b4(Tff7b72!Tb4b4b4(Tff7b72await Te6edf3DialogUtilsTb4b4b4.Te6edf3confirmTb4b4b4(Ta5d6ff"Are you sure you want to remove this audio attachment?"Tb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// remove audio
Tff7b72thisTb4b4b4.Te6edf3newMessageAudio Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3removeFileAttachmentTff7b72: Tff7b72function Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3newMessageFiles Tff7b72= Tff7b72thisTb4b4b4.Te6edf3newMessageFilesTb4b4b4.Te6edf3filterTb4b4b4(Tb4b4b4(Te6edf3newMessageFileTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3newMessageFile Tff7b72!== Te6edf3fileTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3addNewLineTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// get cursor position for message input
Tff7b72const Te6edf3input Tff7b72= Tff7b72thisTb4b4b4.Te6edf3$refsTb4b4b4[Ta5d6ff"message-input"Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3cursorPosition Tff7b72= Te6edf3inputTb4b4b4.Te6edf3selectionStartTb4b4b4;
T8b949e// insert a newline character after the cursor position
Tff7b72const Te6edf3text Tff7b72= Tff7b72thisTb4b4b4.Te6edf3newMessageTextTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3newMessageText Tff7b72= Te6edf3textTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3cursorPositionTb4b4b4) Tff7b72+ Ta5d6ff"\n" Tff7b72+ Te6edf3textTb4b4b4.Te6edf3sliceTb4b4b4(Te6edf3cursorPositionTb4b4b4)Tb4b4b4;
T8b949e// move cursor to the position after the added newline
Tff7b72const Te6edf3newCursorPosition Tff7b72= Te6edf3cursorPosition Tff7b72+ T79c0ff1Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3$nextTickTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3inputTb4b4b4.Te6edf3selectionStart Tff7b72= Te6edf3newCursorPositionTb4b4b4;
Te6edf3inputTb4b4b4.Te6edf3selectionEnd Tff7b72= Te6edf3newCursorPositionTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onEnterPressedTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// add new line on mobile
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3isMobileTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3addNewLineTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// send message on desktop
Tff7b72thisTb4b4b4.Te6edf3sendMessageTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3onShiftEnterPressedTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3addNewLineTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3addFilesToMessageTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3$refsTb4b4b4[Ta5d6ff"file-input"Tb4b4b4]Tb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3findConversationTff7b72: Tff7b72function Tb4b4b4(Te6edf3destinationHashTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3conversationsTb4b4b4.Te6edf3findTb4b4b4(Tb4b4b4(Te6edf3conversationTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3conversationTb4b4b4.Te6edf3destination_hash Tff7b72=== Te6edf3destinationHashTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tff7b72async Te6edf3markConversationAsReadTb4b4b4(Te6edf3conversationTb4b4b4) Tb4b4b4{
T8b949e// manually mark conversation read in memory to avoid delay updating ui
Te6edf3conversationTb4b4b4.Te6edf3is_unread Tff7b72= Tff7b72falseTb4b4b4;
T8b949e// mark conversation as read on server
Tff7b72try Tb4b4b4{
Tff7b72await Tffa657windowTb4b4b4.Te6edf3axiosTb4b4b4.Te6edf3getTb4b4b4(Ta5d6ff`Ta5d6ff/api/v1/lxmf/conversations/Tffd700${Te6edf3conversationTb4b4b4.Te6edf3destination_hashTffd700}Ta5d6ff/mark-as-readTa5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// do nothing if failed to mark as read
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// reload conversations
Tff7b72thisTb4b4b4.Te6edf3$emitTb4b4b4(Ta5d6ff"reload-conversations"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3toggleSentMessageInfoTff7b72: Tff7b72function Tb4b4b4(Te6edf3messageHashTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3expandedMessageInfo Tff7b72=== Te6edf3messageHashTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3expandedMessageInfo Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3expandedMessageInfo Tff7b72= Te6edf3messageHashTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3toggleReceivedMessageInfoTff7b72: Tff7b72function Tb4b4b4(Te6edf3messageHashTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3expandedMessageInfo Tff7b72=== Te6edf3messageHashTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3expandedMessageInfo Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3expandedMessageInfo Tff7b72= Te6edf3messageHashTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Te6edf3getMessageInfoLinesTff7b72: Tff7b72function Tb4b4b4(Te6edf3lxmfMessageTb4b4b4, Te6edf3isOutboundTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3lines Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3isOutboundTb4b4b4) Tb4b4b4{
Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffCreated: Tffd700${Te6edf3UtilsTb4b4b4.Te6edf3convertUnixMillisToLocalDateTimeStringTb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3timestamp Tff7b72* T79c0ff1000Tb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffSent: Tffd700${Te6edf3UtilsTb4b4b4.Te6edf3convertUnixMillisToLocalDateTimeStringTb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3timestamp Tff7b72* T79c0ff1000Tb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffReceived: Tffd700${Te6edf3UtilsTb4b4b4.Te6edf3convertDateTimeToLocalDateTimeStringTb4b4b4(Tff7b72new Tffa657DateTb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3created_atTb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffMethod: Tffd700${Te6edf3lxmfMessageTb4b4b4.Te6edf3method Tff7b72?? Ta5d6ff"unknown"Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3audioTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3audioSize Tff7b72=
Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4.Te6edf3audio_size Tff7b72??
Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4.Te6edf3audio_bytes Tff7b72? Te6edf3atobTb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3audioTb4b4b4.Te6edf3audio_bytesTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72: T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3audioSize Tff7b72> T79c0ff0Tb4b4b4) Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffAudio Attachment: Tffd700${Tff7b72thisTb4b4b4.Te6edf3formatBytesTb4b4b4(Te6edf3audioSizeTb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3imageTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3imageSize Tff7b72=
Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3imageTb4b4b4.Te6edf3image_size Tff7b72??
Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3imageTb4b4b4.Te6edf3image_bytes Tff7b72? Te6edf3atobTb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3imageTb4b4b4.Te6edf3image_bytesTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72: T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3imageSize Tff7b72> T79c0ff0Tb4b4b4) Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffImage Attachment: Tffd700${Tff7b72thisTb4b4b4.Te6edf3formatBytesTb4b4b4(Te6edf3imageSizeTb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTff7b72?Tb4b4b4.Te6edf3file_attachmentsTb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3filesLength Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3fileAttachments Tff7b72= Te6edf3lxmfMessageTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3file_attachmentsTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fileAttachment Tff7b72of Te6edf3fileAttachmentsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3fileBytesLength Tff7b72=
Te6edf3fileAttachmentTb4b4b4.Te6edf3file_size Tff7b72??
Tb4b4b4(Te6edf3fileAttachmentTb4b4b4.Te6edf3file_bytes Tff7b72? Te6edf3atobTb4b4b4(Te6edf3fileAttachmentTb4b4b4.Te6edf3file_bytesTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72: T79c0ff0Tb4b4b4)Tb4b4b4;
Te6edf3filesLength Tff7b72+= Te6edf3fileBytesLengthTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3filesLength Tff7b72> T79c0ff0Tb4b4b4) Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffFile Attachments: Tffd700${Tff7b72thisTb4b4b4.Te6edf3formatBytesTb4b4b4(Te6edf3filesLengthTb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isOutboundTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3quality Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffSignal Quality: Tffd700${Te6edf3lxmfMessageTb4b4b4.Te6edf3qualityTffd700}Ta5d6ff%Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3rssi Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffRSSI: Tffd700${Te6edf3lxmfMessageTb4b4b4.Te6edf3rssiTffd700}Ta5d6ffdBmTa5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3lxmfMessageTb4b4b4.Te6edf3snr Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3linesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffSNR: Tffd700${Te6edf3lxmfMessageTb4b4b4.Te6edf3snrTffd700}Ta5d6ffdBTa5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3linesTb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4<Tb4b4b4/Tff7b72scriptTb4b4b4>
Tb4b4b4<Tff7b72style Te6edf3scopedTb4b4b4>
Tb4b4b4.T56d364attachment-card Tb4b4b4{
@apply relative flex gap-3 border border-gray-200 Te6edf3darkTb4b4b4:Tff7b72borderTff7b72-Te6edf3zinc-800 Te6edf3rounded-2xl Te6edf3p-3 Te6edf3shadow-smTb4b4b4;
Tff7b72background-colorTb4b4b4: Tff7b72whiteTb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364dark Tb4b4b4.T56d364attachment-card Tb4b4b4{
Tff7b72background-colorTb4b4b4: Tffa657rgbTb4b4b4(T79c0ff24 T79c0ff24 T79c0ff27Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-card__preview Tb4b4b4{
@apply w-24 h-24 overflow-hidden rounded-xl bg-gray-100 Te6edf3darkTb4b4b4:Te6edf3bg-zinc-800 Tff7b72cursorTff7b72-Tff7b72pointerTb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-card__body Tb4b4b4{
@apply flex-1Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-card__title Tb4b4b4{
@apply text-sm font-semibold text-gray-800 Te6edf3darkTb4b4b4:Tff7b72textTff7b72-Tff7b72grayT79c0ff-100Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-card__meta Tb4b4b4{
@apply text-xs text-gray-500 Te6edf3darkTb4b4b4:Tff7b72textTff7b72-Tff7b72grayT79c0ff-400Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-card__remove Tb4b4b4{
@apply absolute top-2 right-2 inline-flex items-center justify-center w-6 h-6 rounded-full bg-gray-200 Te6edf3darkTb4b4b4:Te6edf3bg-zinc-800 Tff7b72textTff7b72-Tff7b72grayT79c0ff-600 Te6edf3darkTff7b72:Tff7b72textTff7b72-Tff7b72grayT79c0ff-200 Te6edf3hoverTff7b72:Te6edf3bg-red-100 Te6edf3hoverTff7b72:Tff7b72textTff7b72-Tff7b72redT79c0ff-600 Te6edf3darkTff7b72:Te6edf3hoverTff7b72:Te6edf3bg-red-900Tff7b72/T79c0ff40Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-chip Tb4b4b4{
@apply flex items-center justify-between gap-2 border border-gray-200 Te6edf3darkTb4b4b4:Tff7b72borderTff7b72-Te6edf3zinc-800 Te6edf3rounded-full Te6edf3px-3 Te6edf3py-1 Tff7b72textTff7b72-Te6edf3xs Te6edf3shadow-smTb4b4b4;
Tff7b72background-colorTb4b4b4: Tff7b72whiteTb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364dark Tb4b4b4.T56d364attachment-chip Tb4b4b4{
Tff7b72background-colorTb4b4b4: Tffa657rgbTb4b4b4(T79c0ff24 T79c0ff24 T79c0ff27Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-chip__remove Tb4b4b4{
@apply inline-flex items-center justify-center text-gray-500 Te6edf3darkTb4b4b4:Tff7b72textTff7b72-Tff7b72grayT79c0ff-300 Te6edf3hoverTff7b72:Tff7b72textTff7b72-Tff7b72redT79c0ff-500Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364attachment-action-button Tb4b4b4{
@apply inline-flex items-center gap-1 rounded-full border border-gray-200 Te6edf3darkTb4b4b4:Tff7b72borderTff7b72-Te6edf3zinc-700 Te6edf3bg-whiteTff7b72/T79c0ff90 Te6edf3darkTff7b72:Te6edf3bg-zinc-900Tff7b72/T79c0ff80 Te6edf3px-3 Te6edf3py-1T79c0ff.5 Tff7b72textTff7b72-Te6edf3xs Tff7b72fontTff7b72-Te6edf3semibold Tff7b72textTff7b72-Tff7b72grayT79c0ff-800 Te6edf3darkTff7b72:Tff7b72textTff7b72-Tff7b72grayT79c0ff-100 Te6edf3shadow-sm Te6edf3hoverTff7b72:Tff7b72borderTff7b72-Tff7b72blueT79c0ff-400 Te6edf3darkTff7b72:Te6edf3hoverTff7b72:Tff7b72borderTff7b72-Tff7b72blueT79c0ff-500 Tff7b72transitionTb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364audio-controls-light Tb4b4b4{
Tff7b72filterTb4b4b4: Tffa657invertTb4b4b4(T79c0ff1Tb4b4b4) Tffa657hue-rotateTb4b4b4(T79c0ff180Tffa657degTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364dark Tb4b4b4.T56d364audio-controls-light Tb4b4b4{
Tff7b72filterTb4b4b4: Tff7b72noneTb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364audio-controls-dark Tb4b4b4{
Tff7b72filterTb4b4b4: Tff7b72noneTb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364dark Tb4b4b4.T56d364audio-controls-dark Tb4b4b4{
Tff7b72filterTb4b4b4: Tffa657invertTb4b4b4(T79c0ff1Tb4b4b4) Tffa657hue-rotateTb4b4b4(T79c0ff180Tffa657degTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4<Tb4b4b4/Tff7b72styleTb4b4b4>
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────